在中使用数组awk

在中使用数组awk

我有一个 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

如果输入文件的字段由一个或多个空白字符分隔,则不必声明字段分隔符:

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

NR>1意味着awk将忽略标题(第一行)。

类似地,NF( 的简写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操作后成为第二列。
  • uniq -c- 计算唯一出现的次数

按团队排序的输出:

1 Win Celtics
1 Loss Knicks
1 Win Knicks
2 Loss Lakers
1 Win Lakers

相关内容