
次の列を含む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
各チームの各結果の発生回数をどのように計算して保存できますか?理想的には、このデータをチームごとにソートしたいと思います。
答え1
配列の使用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
ここでは、リーグ(入力ファイル)の各チーム(、最初のゲーム)の勝敗(、4番目のゲーム)の数を数えますleague[$1][$4]++
。$4
$1
NR>1
awk
ヘッダー(最初の行)が無視されることを意味します。
同様にNF
、(の略語)は、1つ以上のフィールドを含む行のみをチェックすることをNF>0
意味します。awk
つまり、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
答え2
あなたがしなければならないのは、ファイルを並べ替えてそれを渡すことによってuniq -c
一意の発生回数を数えることです。
sort teams.csv | uniq -c
これにより、次のような出力が生成されます。
1 Celtics,Win
1 Knicks,Loss
1 Knicks,Win
2 Lakers,Loss
答え3
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
渡す -t,
答え4
ただ使用し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