awk循环遍历一个文件中的所有字段

时间:2014-11-26 16:46:55

标签: sorting csv for-loop awk uniq

此语句为我提供了第1列中唯一值的计数:

awk -F ',' '{print $1}' infile1.csv | sort | uniq -c | sort -nr > outfile1.csv

它完成了我的预期(给出了列中唯一值的计数(左)(右):

117 5
 58 0
 18 4
 14 3
 11 1
  9 2

但是,现在我想创建一个循环,所以它将遍历所有列。 我试过了:

for i in {1..10} 
 do 
   awk -F ',' '{print $$i}' infile.csv | sort | uniq -c | sort -nr > outfile$i.csv
done

这不起作用(它确实生成一个文件,但有更多的数据)。我认为print语句中的一个变量,正如我在print $$ i中尝试的那样,并不是一般的,因为到目前为止我还没有遇到它。

我也试过这个:

awk -F ',' '{for(i=1;i<=NF;i++) infile.csv | sort | uniq -c | sort -nr}' > outfile$i.csv

但是这根本没有给出任何结果(意味着infile和sort命令的语法错误)。我确信我以错误的方式使用for语句。

理想情况下,我希望代码能够找到每列的唯一值计数,并将它们全部打印在同一个输出文件中。但是,我已经对功能良好的循环感到非常满意。

如果这个解释不够好,请告诉我,我会尽力澄清。

2 个答案:

答案 0 :(得分:4)

任何时候你在shell中编写循环只是为了操作文本你都有错误的方法。只需在一个awk命令中执行此操作,类似于使用GNU awk进行2D数组并排序in(未经测试,因为您未提供任何示例输入):

awk -F, '
BEGIN { PROCINFO["sorted_in"] = "@val_num_desc" }
{ for (i=1; i<=NF; i++) cnt[i][$i]++ }
END {
    for (i=1; i<=NF; i++)
        for (val in cnt[i])
            print val, cnt[i][val] > ("outfile" i ".csv")
}
' infile.csv

不需要六个不同的命令,管道等。

答案 1 :(得分:1)

您希望遍历列并在每个列中执行相同的命令。所以你正在做的很好:将列名传递给awk。但是,您需要以不同方式传递值,以便它是awk变量:

for i in {1..10} 
 do 
   awk -F ',' -v col=$i '{print $col}' infile.csv | sort | uniq -c | sort -nr > outfile$i.csv
              ^^^^^^^^^^^^^^^^^^^^^^^^
done