From a5bdbe6b577a2b205b5f9ee552e3c100e4c3a85a Mon Sep 17 00:00:00 2001 From: JustAnotherArchivist Date: Wed, 7 Feb 2024 02:15:06 +0000 Subject: [PATCH] Add uniqify-recent --- uniqify-recent | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100755 uniqify-recent diff --git a/uniqify-recent b/uniqify-recent new file mode 100755 index 0000000..54c8623 --- /dev/null +++ b/uniqify-recent @@ -0,0 +1,52 @@ +#!/bin/bash +if [[ $# -ge 1 && ( $# -gt 1 || ! "$1" =~ ^([0-9]|[1-9][0-9]*)(\.[0-9][0-9]*)?$ ) ]]; then + printf 'Usage: uniqify-recent [N]\n' >&2 + printf 'After a line is read from stdin, its duplicates are suppressed for N seconds (default: 60)\n' >&2 + printf 'N may have a fractional part, e.g. 123456.789\n' >&2 + exit 1 +fi + +# EPOCHREALTIME was added in 4.4 +if (( BASH_VERSINFO[0] < 4 || ( BASH_VERSINFO[0] == 4 && BASH_VERSINFO[1] < 4 ) )); then + printf 'Error: this requires Bash 4.4 or higher\n' >&2 + exit 1 +fi + +limit=60000000 +if [[ $# -eq 1 ]]; then + if [[ "$1" == *.* ]]; then + seconds="${1%.*}" + fraction="${1#*.}" + else + seconds="$1" + fraction= + fi + fraction="${fraction}000000" + fraction="${fraction:0:6}" + limit=$((seconds * 1000000 + fraction)) +fi + +# Bash 5.2 added ridiculousness in arithmetic context expansion of associative arrays. Revert that nonsense. +if (( BASH_VERSINFO[0] > 5 || ( BASH_VERSINFO[0] == 5 && BASH_VERSINFO[1] >= 2 ) )); then + BASH_COMPAT=51 +fi + +declare -A lastseen +lastclean=${EPOCHREALTIME/./} + +while IFS= read -r l; do + now=${EPOCHREALTIME/./} + if [[ ! -v 'lastseen[$l]' ]] || (( now - lastseen[\$l] > limit )); then + printf '%s\n' "$l" + lastseen["${l}"]="${now}" + fi + if (( now - lastclean > 10 * limit )); then + # Purge old entries + for k in "${!lastseen[@]}"; do + if (( now - lastseen[\$k] > limit )); then + unset -v 'lastseen[$k]' + fi + done + lastclean="${now}" + fi +done