选择 awk 中的列丢弃相应的 header

selecting columns in awk discarding corresponding header

如何在一些处理后正确 select awk 中的列。我的文件在这里:

cat foo

A;B;C
9;6;7
8;5;4
1;2;3

我想添加带有行号的第一列,然后提取结果的一些列。例如,让我们获取新的第一列(行号)和第三列。这样:

 awk -F';' 'FNR==1{print "linenumber;"[=12=];next} {print FNR-1,,}' foo

给我这个意想不到的输出:

linenumber;A;B;C
1 9 7
2 8 4
3 1 3

但预期是(注意 B 现在是第三列,因为我们将行号添加为第一列):

linenumber;B
1;6
2;5
3;2

[修复和修订]

为什么要在 header 中打印 [=14=](完整记录)?而且,如果您只想在输出中显示两列,为什么要打印 3(FNR-1</code> 和 <code>)?最后,您的输出字段分隔符是空格而不是预期的 ; 的原因很简单……您没有指定输出字段分隔符 (OFS)。您可以使用命令行变量赋值 (OFS=\;) 执行此操作,如下面的第二个和第三个版本所示,但也可以使用 -v 选项 (-v OFS=\;) 或 BEGIN block (BEGIN {OFS=";"}) 随心所欲(这3种方法有区别,但在这里不重要)。

[编辑]:最后查看通用解决方案。

如果您要保留的字段是输入文件的第二个字段(B 列),请尝试:

$ awk -F\; 'FNR==1 {print "linenumber;" ; next} {print FNR-1 ";" }' foo
linenumber;B
1;6
2;5
3;2

$ awk -F\; 'FNR==1 {print "linenumber",; next} {print FNR-1,}' OFS=\; foo
linenumber;B
1;6
2;5
3;2

注意,只要你不想保留输入文件的第一个字段(</code>),你也可以用行号覆盖它:</p> <pre><code>$ awk -F\; '{=FNR==1?"linenumber":FNR-1; print ,}' OFS=\; foo linenumber;B 1;6 2;5 3;2

最后,这是一个更通用的解决方案,您可以向其中传递要打印的输入文件的列索引列表(本例中为 1 和 3):

$ awk -F\; -v cols='1;3' '
  BEGIN { OFS = ";"; n = split(cols, c); }
  { printf("%s", FNR == 1 ? "linenumber" : FNR - 1);
    for(i = 1; i <= n; i++) printf("%s", OFS $(c[i]));
    printf("\n");
  }' foo
linenumber;A;C
1;9;7
2;8;4
3;1;3

要获得预期的输出,请使用:

$ awk 'BEGIN {
    FS=OFS=";"
}
{
    print (FNR==1?"linenumber":FNR-1),$(FNR==1?3:1)
}' file

输出:

linenumber;C
1;9
2;8
3;1

添加带有行号的列并提取第一列和最后一列,请使用:

$ awk 'BEGIN {
    FS=OFS=";"
}
{
    print (FNR==1?"linenumber":FNR-1),,$NF
}' file

本次输出:

linenumber;A;C
1;9;7
2;8;4
3;1;3