The little things give you away... A collection of various small helper stuff
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

53 lines
1.4 KiB

  1. #!/bin/bash
  2. if [[ $# -ge 1 && ( $# -gt 1 || ! "$1" =~ ^([0-9]|[1-9][0-9]*)(\.[0-9][0-9]*)?$ ) ]]; then
  3. printf 'Usage: uniqify-recent [N]\n' >&2
  4. printf 'After a line is read from stdin, its duplicates are suppressed for N seconds (default: 60)\n' >&2
  5. printf 'N may have a fractional part, e.g. 123456.789\n' >&2
  6. exit 1
  7. fi
  8. # EPOCHREALTIME was added in 4.4
  9. if (( BASH_VERSINFO[0] < 4 || ( BASH_VERSINFO[0] == 4 && BASH_VERSINFO[1] < 4 ) )); then
  10. printf 'Error: this requires Bash 4.4 or higher\n' >&2
  11. exit 1
  12. fi
  13. limit=60000000
  14. if [[ $# -eq 1 ]]; then
  15. if [[ "$1" == *.* ]]; then
  16. seconds="${1%.*}"
  17. fraction="${1#*.}"
  18. else
  19. seconds="$1"
  20. fraction=
  21. fi
  22. fraction="${fraction}000000"
  23. fraction="${fraction:0:6}"
  24. limit=$((seconds * 1000000 + fraction))
  25. fi
  26. # Bash 5.2 added ridiculousness in arithmetic context expansion of associative arrays. Revert that nonsense.
  27. if (( BASH_VERSINFO[0] > 5 || ( BASH_VERSINFO[0] == 5 && BASH_VERSINFO[1] >= 2 ) )); then
  28. BASH_COMPAT=51
  29. fi
  30. declare -A lastseen
  31. lastclean=${EPOCHREALTIME/./}
  32. while IFS= read -r l; do
  33. now=${EPOCHREALTIME/./}
  34. if [[ ! -v 'lastseen[$l]' ]] || (( now - lastseen[\$l] > limit )); then
  35. printf '%s\n' "$l"
  36. lastseen["${l}"]="${now}"
  37. fi
  38. if (( now - lastclean > 10 * limit )); then
  39. # Purge old entries
  40. for k in "${!lastseen[@]}"; do
  41. if (( now - lastseen[\$k] > limit )); then
  42. unset -v 'lastseen[$k]'
  43. fi
  44. done
  45. lastclean="${now}"
  46. fi
  47. done