|
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152 |
- #!/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
|