次の内容を含む複数のファイルがあります。
GGHTERR_01218 GGHTERR_02418 GGHTERR_01991
GGHTERR_02211 GGHTERR_02297 GGHTERR_02379
GGHTERR_02294 GGHTERR_02455 GGHTERR_02374
GGHTERR_00532 GGHTERR_00534
GGHTERR_00533 GGHTERR_00535
GGHTERR_00776 GGHTERR_00779
GGHTERR_01220 GGHTERR_01620
GGHTERR_01760 GGHTERR_01761
GGHTERR_01774 GGHTERR_02404
GGHTERR_01889 GGHTERR_01890
GGHTERR_02081 GGHTERR_02287
GGHTERR_02152 GGHTERR_02153
GGHTERR_02260 GGHTERR_02321
GGHTERR_02295 GGHTERR_02375
GGHTERR_02419 GGHTERR_02437
GGHTERR_02420 GGHTERR_02438
GGHTERR_02430 GGHTERR_02448
GGHTERR_00001
GGHTERR_00002
GGHTERR_00003
GGHTERR_00004
GGHTERR_00005
GGHTERR_00006
GGHTERR_00007
3列、2列、1列の行数を簡単に計算する方法があるかどうかを知りたいです。
したがって、出力は次のようになります。
3 columns: 3
2 columns: 14
1 colums: 7
答え1
Awkはこれに最適です。スペースで行を分割し(デフォルトではoptionsに変更-F
)、内部変数NF
(フィールド数)には1行あたりのフィールド数があります。したがって、ファイルを見て、NF
各行を保存します。
awk '{
nums[NF]++
}
END{
for(num in nums){
printf "%d columns: %d\n", num, nums[num]
}
}' file
上記のコードは単にNF
フィールド数()を連想配列に格納します。nums
ここで、キーはフィールド数、値はファイル内の列番号が見つかった回数です。最後に、配列を繰り返し印刷します。上記の例を実行すると、次の結果が得られます。
$ awk '{ nums[NF]++}END{for(num in nums){printf "%d columns: %d\n", num, nums[num]}}' file
1 columns: 7
2 columns: 14
3 columns: 3
このアプローチの1つの(マイナーな)欠点は、ファイルの各行のエントリをメモリに保持する必要があることです。ファイルが非常に大きい場合、または利用可能なメモリがほとんどない場合は問題ありません。ただし、その場合は、1行あたりのフィールド数を印刷して計算して問題を解決できます。
$ awk '{ print NF}' file | sort | uniq -c
7 1
14 2
3 3
または、同じ出力を得るには、次のようにします。
$ awk '{ print NF}' file | sort | uniq -c | while read num fields; do printf "%d columns: %d\n" "$num" "$fields"; done
7 columns: 1
14 columns: 2
3 columns: 3
答え2
非awk
ソリューション、おそらく少し面倒です。
$ a=$(grep '^[GHTER_0-9]\+[[:space:]]\+[GHTER_0-9]\+[[:space:]]\+[GHTER_0-9]\+$' file | wc -l)
$ b=$(grep '^[GHTER_0-9]\+[[:space:]]\+[GHTER_0-9]\+$' file | wc -l)
$ c=$(grep '^[GHTER_0-9]\+$' file | wc -l)
$ printf "3 columns %s\n2 columns %s\n1 column %s\n" $a $b $c
3 columns 3
2 columns 14
1 columns 7