我有一个逗号分隔的文本文件。第一行是字段名称列表,后续行包含数据。我将获得该文件的新版本,并且我希望按名称而不是列号从特定列中提取所有值。 (即我想要的列可能在文件的不同版本中处于不同的位置。)
例如,这里有两个文件:
foo,bar,interesting,junk
1,2,gold,ramjet
2,25,diamonds,superfluous
和
foo,bar,baz,interesting,junk,morejunk
5,3,smurf,platinum,garbage,scrap
6,2.5,mushroom,sodium,liverwurst,eew
我喜欢一个单独的脚本,它将通过多个文件,提取有趣的"中的矿物质。柱。 : - )
我到目前为止所获得的是一个文件,但我知道awk比这更优雅。如何清理它并使其一次处理多个文件?
BEGIN {
FS=",";
}
NR == 1 {
for(i=1; i<=NF; i++) {
if($i=="interesting") {
col=i;
}
}
}
NR > 1 {
print $col;
}
答案 0 :(得分:2)
你已经非常接近了。只需使用FNR而不是NR,用于&#34;文件NR&#34;。
#!/usr/bin/awk -f
BEGIN { FS="," }
FNR==1 {
for (col=1;col<=NF;col++)
if ($col=="interesting")
next
}
{ print $col }
或者如果您愿意:
#!/usr/bin/awk -f
BEGIN { FS="," }
FNR==1 { for (col=1;$col!="interesting";col++); next }
{ print $col }
或者如果您更喜欢单行:
$ awk -F, -v txt="interesting" 'FNR==1{for(c=1;$c!=txt;c++);next} {print $c}' file1 file2
当然,要小心你实际上有指定的列,否则你可能会发现自己处于无限循环中。您可以找出可以避免这种风险的额外条件。
请注意,在awk中,如果后面跟着另一个命令,则只需要用分号终止命令。因此,你会这样做:
command1; command2
但如果用新行分隔命令,则可以删除分号:
command1
command2
答案 1 :(得分:2)
这样做:
$ cat tst.awk
BEGIN { FS=OFS="," }
FNR==1 { for (i=1;i<=NF;i++) f[$i]=i; next }
{ print $(f["interesting"]) }
$ awk -f tst.awk file1 file2
gold
diamonds
platinum
sodium
创建名称 - &gt;值数组始终是适用的最佳方法。它使代码的每个部分都保持简单并与代码的其余部分分离,并且它可以帮助您进行其他操作,例如在输出结果时更改字段的顺序,例如:
$ cat tst.awk
BEGIN { FS=OFS="," }
FNR==1 { for (i=1;i<=NF;i++) f[$i]=i; next }
{ print $(f["junk"]), $(f["interesting"]), $(f["bar"]) }
$ awk -f tst.awk file1 file2
ramjet,gold,2
superfluous,diamonds,25
garbage,platinum,3
liverwurst,sodium,2.5