次のような内容のファイルがいくつかあります。
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 はこれに最適です。行を空白で分割し (デフォルト。オプションで変更可能-F
)、内部変数(フィールド数) に行あたりのフィールド数が格納されます。したがって、ファイルを調べて、各行の をNF
保存するだけです。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 つの (小さな) 欠点は、ファイル内の各行のエントリをメモリ内に保持する必要があることです。ファイルが非常に巨大であるか、使用可能なメモリが非常に少ない場合を除いて、これは問題になりませんが、そのような場合は、行ごとにフィールドの数を出力してカウントするだけで回避できます。
$ 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