次のような列を持つCSVがあります。
Team Other Data More Data Result Time
Knicks A F Loss 2p
Celtics B E Win 2p
Lakers C D Loss 3p
Lakers D C Loss 4p
Knicks E B Win 4p
Lakers F A Win 5p
CSVを読み取って各チームの勝敗を出力するにはどうすればよいですか?
たとえば、希望する出力は次のようになります。
1 Loss Knicks 1 Win Knicks 1 Win Celtics 2 Loss Lakers 1 Win Lakers
今、私はこのコードを持っています:
#!/bin/bash
while IFS=, read -r team result
do
echo $team, $result
done < teams.csv
これにより、次の出力が生成されます。
Team, Result
Knicks, Loss
Celtics, Win
Lakers, Loss
Lakers, Loss
Knicks, Win
すべてのチームの各結果の発生数をカウントして保存するにはどうすればよいですか?理想的には、このデータをチームごとに並べ替えたいです。
awk
での配列の使用入力ファイルのフィールドが1つ以上の空白文字で区切られている場合は、フィールド区切り文字を宣言する必要はありません。
awk 'NR>1 && NF { league[$1][$4]++ } END { for ( team in league ) for ( results in league[team] ) print league[team][results],results,team }' teams.txt
画面用にフォーマットされた同じコード:
awk 'NR>1 && NF { league[$1][$4]++ }
END { for ( team in league )
for ( results in league[team] )
print league[team][results],results,team }' teams.txt
ここで、league[$1][$4]++
は、リーグ(入力ファイル)の各チーム($4
、最初のフィールド)の勝ち負けの数($1
、4番目のフィールド)をカウントします。
NR>1
は、awk
がヘッダー(最初の行)を無視することを意味します。
同様に、NF
(NF>0
の省略形)は、awk
が少なくとも1つのフィールドを含む行のみを検査することを意味します。つまり、NF
は空白行をスキップします。
NR>1 && NF
セクションは、入力ファイルを調べて配列を作成します。それが終了すると、END
セクションは配列を出力します。
入力ファイルのフィールドがカンマで区切られている場合は、BEGIN { FS="," ; OFS=" " }
を追加して、入力(FS
)と出力(OFS
)のフィールド区切り記号を設定します。
awk 'BEGIN { FS="," ; OFS=" " } NR>1 && NF { league[$1][$4]++ } END { for ( team in league ) for ( results in league[team] ) print league[team][results],results,team }' teams.csv
画面用にフォーマットされた同じコード:
awk 'BEGIN { FS="," ; OFS=" " }
NR>1 && NF { league[$1][$4]++ }
END { for ( team in league )
for ( results in league[team] )
print league[team][results],results,team }' teams.csv
出力:
1 Win Knicks
1 Loss Knicks
1 Win Lakers
2 Loss Lakers
1 Win Celtics
そのコードの最後に| sort -t " " -k 3 -k 2,2
を追加して、チームで並べ替えてから、チームごとの結果で並べ替えます。
ソートされた出力:
1 Win Celtics
1 Loss Knicks
1 Win Knicks
2 Loss Lakers
1 Win Lakers
あなたがする必要があるのは、ファイルをソートし、それをuniq -c
に渡して、一意の発生をカウントすることです。
sort teams.csv | uniq -c
次のような出力が生成されます。
1 Celtics,Win
1 Knicks,Loss
1 Knicks,Win
2 Lakers,Loss
GNU datamash(およびawkを使用すると、必要に応じて列を並べ替えることができます):
$ datamash -W --header-in groupby 1,4 count 4 < teams.csv | awk '{print $3, $2, $1}'
1 Loss Knicks
1 Win Celtics
2 Loss Lakers
1 Win Knicks
1 Win Lakers
しない datamashにソートを要求するため、これはすでに隣接している結果のみをグループ化することに注意してください。
あなたのデータが本当にカンマ分離されている場合は、置き換えてください-W
by-t,
sort
を使用して、それをuniq -c
にパイプすることができますが、これにはTeam, Result
が含まれます。
それを回避するには:
$ awk 'NR>1 {print $4,$1}' team.csv | sort -k2 | uniq -c
各セクションを説明するには:
awk 'NR>1 {print $4,$1}'
-最初の行よりも大きいすべての行を印刷します。結果は、チームと結果の列4と1で指定されたチームが続きます。sort -k2
-awk
の運用後、2列目になるようにチームで並べ替えます。uniq -c
-一意のオカレンスの数をカウントしますチーム別にソートされた出力:
1 Win Celtics
1 Loss Knicks
1 Win Knicks
2 Loss Lakers
1 Win Lakers