按标题名称以awk打印列


12

我有一个像这样的文本文件

foo bar baz
1   a   alpha
2   b   beta
3   c   gamma

我可以使用awk通过来打印某些列,例如1和3,{print $1, $3}但是我想通过指定列的标题来指定要打印的列,例如{print $foo, $baz}。这很有用,因此我不必打开文件并手动对列进行计数即可查看哪一列,并且如果列号或顺序发生更改,我也不必更新脚本。我可以使用awk(或其他shell工具)执行此操作吗?

Answers:


17
awk '
NR==1 {
    for (i=1; i<=NF; i++) {
        f[$i] = i
    }
}
{ print $(f["foo"]), $(f["baz"]) }
' file
foo baz
1 alpha
2 beta
3 gamma

这是一个非常有用的习语。我在电子表格中有很多数据,不同的电子表格可能会有我感兴趣的列的子集,但不一定在所有电子表格中的列顺序相同,或者在它们之间/之前的其他列数相同,因此能够导出将它们转换为CSV或类似格式,然后仅使用列名而不是列号运行awk脚本是绝对无价的。


非常感谢,并为此而努力。您能否阐明它对awk初学者的工作原理?f [$ i]的语法是什么?awk如何计算出哪些列与字符串匹配?
AlexLipp

别客气。那绝对是awk的基本语法,只需在awk手册页(或google)中查找字段和数组即可。在循环中添加print iand print $iprint f [$ i]`语句等,以跟踪发生的情况(如果有帮助的话)。
Ed Morton

1

您可以要求awk,但您也可以为此使用更专业的工具:csvtool

csvtool -t ' ' -u ' ' namedcol foo,baz file

要么

csvtool -t ' ' -u ' ' col 1,3 file

1

假设该文件是TSV(“制表符分隔的值”)文件,请使用csvkit

$ csvcut -t -c foo,baz file.tsv
foo,baz
1,alpha
2,beta
3,gamma

输出将采用格式正确的CSV,但可以轻松更改回TSV:

$ csvcut -t -c foo,baz file.tsv | csvformat -T
foo     baz
1       alpha
2       beta
3       gamma

-c选项csvcut还可以采取数字和范围,并且还可以用来重新排列的输入数据的列(特征我经常错过在标准cut实用程序)。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.