web-dev-qa-db-ja.com

コマンドラインツールを使用して、ソートされたシーケンス内の重複をカウントする

ログファイルを検索して一連の数値を除外するコマンド(cmd1)があります。番号はランダムな順序なので、sort -grを使用して、番号の逆ソートリストを取得します。このソートされたリスト内に重複がある可能性があります。リスト内の一意の番号ごとにカウントを見つける必要があります。

例えばcmd1の出力が次の場合:

100 
100 
100 
99 
99 
26 
25 
24 
24

上記の出力をパイプできる別のコマンドが必要なので、次のようになります。

100     3
99      2
26      1
25      1
24      2
69
letronje

どうですか。

$ echo "100 100 100 99 99 26 25 24 24" \
    | tr " " "\n" \
    | sort \
    | uniq -c \
    | sort -k2nr \
    | awk '{printf("%s\t%s\n",$2,$1)}END{print}'

結果は次のとおりです。

100 3
99  2
26  1
25  1
24  2

uniq -cは、GNU uniq 8.23に対して少なくとも機能し、入力をソートすると仮定して)必要なことを正確に行います。

44
Ibrahim

順序が重要でない場合

# echo "100 100 100 99 99 26 25 24 24" | awk '{for(i=1;i<=NF;i++)a[$i]++}END{for(o in a) printf "%s %s ",o,a[o]}'
26 1 100 3 99 2 24 2 25 1
10
ghostdog74

数値を逆順に並べ替えてから、重複を数え、左右の単語を入れ替えます。列に揃えます。

printf '%d\n' 100 99 26 25 100 24 100 24 99 \
   | sort | uniq -c | sort -nr | awk '{printf "%-8s%s\n", $2, $1}'
100     3
99      2
26      1
25      1
24      2
5
ericcurtin

Bashでは、連想配列を使用して、各入力値のインスタンスをカウントできます。コマンド$cmd1があると仮定します。

#!/bin/bash

cmd1='printf %d\n 100 99 26 25 100 24 100 24 99'

次に、関連する配列エントリで++数学演算子を使用して、配列変数aの値をカウントできます。

while read i
do
    ((++a["$i"]))
done < <($cmd1)

結果の値を出力できます:

for i in "${!a[@]}"
do
    echo "$i ${a[$i]}"
done

出力の順序が重要な場合、キーの外部sortが必要になる場合があります。

for i in $(printf '%s\n' "${!a[@]}" | sort -nr)
do
    echo "$i ${a[$i]}"
done
2
Toby Speight