如何使用 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 awk
and 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' file
或awk 'print $(NF-1), $NF' file
或awk '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 打印最后两列的主要内容,如果未能解决你的问题,请参考以下文章