如何使用 awk 打印最后两列

Posted

技术标签:

【中文标题】如何使用 awk 打印最后两列【英文标题】:How to print last two columns using awk 【发布时间】:2011-05-17 08:04:45 【问题描述】:

我只想打印最后两列。

【问题讨论】:

不太清楚为什么它有 87 个赞成票,至少可以通过一个例子来改进它。 可能是因为这个问题本质上非常简单,没有示例也很容易理解,这种情况很少见,但在这种情况下它似乎有效。我认为这里的问题不在于缺乏信息,而更多的是它表明缺乏独立研究。 这个问题也是this问题的重复。 这能回答你的问题吗? Print second last column/field in awk 【参考方案1】:

请尝试这样做以考虑所有可能的情况:

awk 'print $(NF-1)"\t"$NF'  file

awk 'BEGINOFS="\t"' file

awk 'print $(NF-1), $NF print $(NF-1), $NF' file

【讨论】:

【参考方案2】:

试试这个

$ cat /tmp/topfs.txt
/dev/sda2      xfs        32G   10G   22G  32% /

awk print last column
$ cat /tmp/topfs.txt | awk 'print $NF'

awk print before last column
$ cat /tmp/topfs.txt | awk 'print $(NF-1)'
32%

awk - print last two columns
$ cat /tmp/topfs.txt | awk 'print $(NF-1), $NF'
32% /

【讨论】:

【参考方案3】:

使用 gawk 会出现问题:

 gawk ' print $NF-1, $NF' filename
1 2
2 3
-1 one
-1 three
# cat filename
1 2
2 3
one
one two three

我只是在 Solaris 10 M4000 上安装了 gawk: 因此,gawk 是 $NF-1 与 $(NF-1) 问题上的焦点。下一个问题 POSIX 说什么? 每:

http://www.opengroup.org/onlinepubs/009695399/utilities/awk.html

没有一种方向或另一种方向。不好。 gawk 表示减法,其他 awk 表示字段编号或减法。嗯。

【讨论】:

示例输入文件的前 2 行没有帮助,因为它们产生具有 either 行为的相同输出。您能否再次确认 Solaris awk 在这种情况下的行为确实不像 gawk? 关于 awk 规范的链接:使用 $(NF-1) 的轶事参数是规范中计算字段索引的两个示例都使用该形式:$(NF-1)$(NF+2) .然后是“awk 中的表达式”部分,其中列出了$expr 的优先级高于expr - expr。因为NF 本身就是一个表达式,所以$NF-1 的计算结果应该是($NF)-1。毕竟,即使确实有 awk 实现将$NF-1 评估为$(NF-1),这里学到的教训是使用$(NF-1) 是安全且可移植的选择。【参考方案4】:

@jim mcnamara:尝试在NF 周围使用括号,即。 e. $(NF-1)$(NF) 而不是 $NF-1$NF(适用于 Mac OS X 10.6.8 for FreeBSD awkand gawk)。

echo '
1 2
2 3
one
one two three
' | gawk 'if (NF >= 2) print $(NF-1), $(NF);'

# output:
# 1 2
# 2 3
# two three

【讨论】:

我们之前已经考虑过()。我以为我们正在讨论原始的旧 awk 行为的来源。 +1 表示明确的$(NF-1) 答案——至少比$NF-1 更便携;它肯定不那么模棱两可。不过,$(NF) 有点矫枉过正——只需$NF 就可以了。防范少于 2 列的行也是值得的,因为对于单列行,您将获得第一列值 两次,而对于零列(即空行),awk 命令将由于尝试访问索引为 -1 的字段而完全失败。 我认为我们可以让它更短一点:gawk 'NF>=2 print $(NF-1), $NF'【参考方案5】:

您可以使用变量NF,它设置为输入记录中的字段总数:

awk 'print $(NF-1),"\t",$NF' file

这假设您至少有 2 个字段。

【讨论】:

你需要一个逗号 - 因为我们今天很挑剔:空格连接字段,逗号分隔打印语句中的字段。这将合并两个字段 现在您正在打印“field-OFS-tab-OFS-field”。应该是awk 'print $(NF-1) "\t" $NF' fileawk 'print $(NF-1), $NF' fileawk 'BEGINOFS="\t" print $(NF-1), $NF' file 只是添加到前面的评论,使用'print $x,"\t",$y' 的问题是awk 将每个逗号分隔的变量解释为它自己的字段,所以结果实际上是field1<space><tab><space>field2,(因为它会默认情况下使用空格分隔符)而不是field1<tab>field2,这可能是您所期望的。使用输出字段分隔符 (OFS) 几乎总是您想要的。【参考方案6】:
awk 'print $NF-1, $NF'  inputfile

注意:这仅在至少存在两列时才有效。在只有一列的记录上,你会得到一个虚假的"-1 column1"

【讨论】:

试试看。它确实适用于 Solaris 9 awk 和 nawk。另一种选择是 $(NF-1) @coaddict - 我猜你没有使用不同的 awk 实现。旧的 awks 行为已经(可能是错误地)被提出来。我没有 gawk 来测试——这可能是你所引用的。所以我不确定你的评论为什么会被放弃。开箱即用的 Linux awk 通常是 gawk。我会测试并回帖。同时尝试 Soalris 或 HPUX 或 DGX 或其他任何东西,看看我所说的旧 awk 是什么意思。 您可能因为尝试了echo 1 2 3 | awk ... 而误以为它有效。 $NF-1 在每个 awk 实现中都是 ($NF) - 1 “一个真正的 awk”源代码在 yacc 语法中有 40 多个冲突,考虑到 A 在 awk 中的含义,这具有讽刺意味。不同版本的 awk 解析事物的方式不同?大惊喜! @THESorcerer,尝试使用echo '5 4 3 2 1' | awk 'print $NF-1,$NF; print $(NF-1), $NF' -- 或任何其他倒数第二个字段不小于最后一个字段的输入。

以上是关于如何使用 awk 打印最后两列的主要内容,如果未能解决你的问题,请参考以下文章

linux之awk使用技巧

如何使用 shell(awk、sed 等)删除文件中的前两列

awk 如何去除最后一个分隔字符

在`awk`中打印倒数第二列/字段

使用 awk 打印从第 n 到最后的所有列

如何使用 awk 打印匹配的正则表达式模式?