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

214

我想在awk中打印倒数第二列或字段。字段的数量是NF变量。我知道应该能够使用$NF,但我不确定如何使用它。

而这个似乎行不通:

awk ' { print ( $NF-- )  } '

11
NF是最后一个字段的索引,$NF是最后一个字段的值。 - glenn jackman
那现在有意义了。我想这就是为什么括号外的美元符号起作用的原因。 - Brian G
10个回答

366
awk '{print $(NF-1)}'

应该可以正常工作


2
这对我不起作用。在Ubuntu下的awk 3.1.8中,我得到了“title:5: command not found: NF-1”。 - Gurgeh
3
为确保不更改 $NF 的值,建议避免使用前/后缀递减。 - Gregory Patmore
如果您尝试获取第三个最后一个字段,例如 awk -F '.' '{print $(NF-2)}',则会出现错误。 - gies0r
5
因为 $(..) 会在子shell中调用命令,这取决于你使用的是哪个shell。可以通过使用 $ (NF-1) 替换 $(NF-1) 来解决这个问题。 - wting
@wting:你的解释完全错了 - 这里与 shell 没有任何关系 - $(...) 只是 awk 中一种将操作分组的方式,产生的结果可以被评估为某个字段号。如果你愿意,你可以做 $( atan2(0, -1) ) - 它将简单地变成 $(3.14159...),然后自动截断为 $3gawknawk 甚至愿意接受 +/- nan 作为有效的 NF - RARE Kpop Manifesto
显示剩余9条评论

25

对Chris Kannon的回答进行小补充:只有在实际存在倒数第二列时才打印。

(
echo       | awk 'NF && NF-1 { print ( $(NF-1) ) }'
echo 1     | awk 'NF && NF-1 { print ( $(NF-1) ) }'
echo 1 2   | awk 'NF && NF-1 { print ( $(NF-1) ) }'
echo 1 2 3 | awk 'NF && NF-1 { print ( $(NF-1) ) }'
)

22

最简单的方法是:

 awk '{print $--NF}' 
原本的 $NF-- 语句不起作用是因为该表达式在递减之前被计算,而我的前缀递减是在计算之前执行的。
理由是原始的 $NF-- 不起作用是因为在递减之前对表达式进行了评估,而我的前缀递减是在评估之前执行的。

作为助记符,这种行为与C/Java等语言相同。int x = ++i int x = i++,前缀表示先增加;后缀表示先赋值再增加。 - Weekend

11
awk ' { print ( $(NF-1) ) }' file

8

您离结果并不远!这就是它:

awk '{NF--; print $NF}' file

这会减少一个字段的数量,因此$NF包含前次的倒数第二个。

测试

让我们生成一些数字并将它们分组打印出来:

$ seq 12 | xargs -n5
1 2 3 4 5
6 7 8 9 10
11 12

让我们打印每行的倒数第二个:

$ seq 12 | xargs -n5 | awk '{NF--; print $NF}'
4
9
11

6

先对值进行减一操作,然后再打印它-

awk ' { print $(--NF)}' file

或者

rev file|cut -d ' ' -f2|rev

4

与Chris Kannon的awk解决方案类似的Perl解决方案:

perl -lane 'print $F[$#F-1]' file

这些命令行选项被用于:
  • n:循环处理输入文件的每一行,不自动打印每一行。

  • l:在处理之前删除换行符,并在处理完之后添加回去。

  • a:自动拆分模式 - 将输入行拆分成 @F 数组。默认按空格拆分。

  • e:执行 Perl 代码。

@F 自动拆分数组从索引 [0] 开始,而 awk 字段从 $1 开始。
$#F@F 中元素的数量。


3
或者使用 Perl 已经提供的负数索引... $F[-2]。该语句表示从后往前数第二个元素,可用于访问数组中的元素。注意,其中的 $F 是一个数组变量。 - Sundeep

2

您是否尝试使用rev命令从右向左开始?这种情况下,您只需要打印第二列:

seq 12 | xargs -n5 | rev | awk '{ print $2}' | rev
4
9
11

1
如果你有很多列,想要打印除了最后三列之外的所有列,那么这个命令可能会有帮助。
awk '{ $NF="";$(NF-1)="";$(NF-2)="" ; print $0 }'

如果你只想获取除最后3个以外的所有内容,可以使用以下命令: mawk '3 < NF && NF -= 3'2022年7月9日,东部夏令时下午12点30分20秒 星期六,7月9日 - RARE Kpop Manifesto

0
date
Sat Jul  9 11:57:36 EDT 2022

date | gawk '$_=$--NF'

     | mawk '$!--NF=$NF'
EDT

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接