D0000.efficient-history-erasedups.sh (1997B)
1 #!/bin/bash 2 3 function erasedupA.1 { 4 local line="$1" i j 5 for((i=0;i<${#hist[@]};i++)); do 6 if test "${hist[$i]}" != "$line"; then 7 hist[j++]="${hist[$i]}" 8 fi 9 done 10 for((i=${#hist[@]}-1;i>=j;i--)); do 11 unset "hist[$i]" 12 done 13 } 14 15 # + 今迄に同じ物は二つ以上ないと考えると、一つ見つければ OK 16 # 一つだけ削除すればよいのであれば、 17 # パラメータ展開の配列の添字範囲指定で削除する項目の前後の系列を取り出せる。 18 # + 複数実行されたコマンドは最近実行された方が残されているので、 19 # 末尾から探索した方が速いはずである。 20 # + また、複数回実行されていなくても、同じコマンドは同じ時期に実行される傾向があるはずだから、 21 # その点からも末尾から探索した方が良い。 22 function erasedupA.2 { 23 local line="$1" i 24 for((i=${#hist[@]}-1;i>=0;i--)); do 25 if test "${hist[$i]}" = "$line"; then 26 hist=("${hist[@]::i}" "${hist[@]:i+1}") 27 break 28 fi 29 done 30 } 31 32 function erasedupA { 33 local -a hist=() 34 local n=0 35 while read -r line; do 36 echo "# = ${#hist[@]} / $((++n))" 1>&2 37 erasedup2.1 "$line" 38 hist+=("$line") 39 done < ~/.bash_history 40 41 for((i=0;i<${#hist[@]};i++)); do 42 echo "${hist[$i]}" 43 done >| bash_history.erasedupA 44 } 45 46 # + というか逆順に探索すれば初見の物だけ登録するだけでは? 47 # 配列の中で要素を移動させる必要はない。 48 function erasedupB { 49 echo load... >&2 50 declare -a hist1=() 51 while read -r line; do 52 hist1+=("$line") 53 done < ~/.bash_history 54 55 echo uniq... >&2 56 declare -A buff=() 57 declare -a hist2=() 58 for ((i=${#hist1[@]}-1;i>=0;i--)); do 59 local line="${hist1[$i]}" 60 #echo "$line" 61 test -n "${buff[x$line]}" && continue 62 buff[x$line]=1 63 hist2+=("$line") 64 done 65 66 echo output... >&2 67 for ((i=${#hist2[@]}-1;i>=0;i--)); do 68 echo "${hist2[$i]}" 69 done >| bash_history.erasedup 70 } 71 72 erasedupB