无法理解 awk 的打印数组结果?

无法理解 awk 的打印数组结果?

对于一个简单的file包含:

1        a
2        b
3        c
4        d
5        e
6        f
7        g
8        h
9        i
10       j

我使用该命令:

awk 'lines[NR]=$0 { print $lines[2]}' 

它为我提供:

1        a
b
c
d
e
f
g
h
i
j

如何以及为何?不应该是这样吗?

2 b

另外,当我更新以下内容时

awk '{lines[NR]=$0} END { print lines[2]}' awk.write

2 b

与使用$

j

答案1

您混淆了awk变量和工作流程。您可能想要的是(仅打印第二行):

awk '{lines[NR]=$0} END{print lines[2]}' file

但这可以通过以下方式更简单地完成:

awk 'NR==2' file

您命令您的问题执行以下操作:

awk 'lines[NR]=$0 { print $lines[2]}' 
  • lines[NR]=$0这在这里被解释awk为条件。请注意, awk有一个工作流程具有这样的机制(适用于每一行):'condition{instructions}'lines[NR]=$0填充数组,但它是一个始终为真的条件。这就是为什么指令{...}块针对每一行运行。
  • print $lines[2]这不会打印数组的第二项lines[2]$lines[2]扩展为一个变量,其名称是数组中第二项的内容。对于第一行,它是未初始化的,因此print它调用时不带参数。这意味着它会打印整行。但当设置后(在所有其他行中),它​​会扩展为print $2.这意味着,打印该行的第二个字段。

答案2

在 中awk,您可以通过引用来访问变量的值:

$ awk 'BEGIN {var=1; print var}'
1

特殊变量,称为字段变量,用$符号表示,后跟数字或表达式。所以 和$1都给$(0+1)你第一个字段的值。

在您的示例中,您创建了一个关联数组lines,其键是行号,值是整行。要获取 key 的值2,您必须使用lines[2].对于$lines[2],您引用了第 n 个字段,其中 nth 是 的返回值lines[2]

当您处理第一行时,lines[2]未初始化,因此它可能会返回0或者空的或其他什么(POSIX 未指定该行为)。无论如何,printprint $0是相同的,这就是为什么你有1 a,它是$0第一行。

从第二行开始,lines[2]由第二行的内容分配,即2 b,在数字上下文中,2 b返回2,您从第二行获得第二个字段的值$2,依此类推。


现在,由于不保证 after 的表达式$返回 POSIX 指定的数字结果:

字段变量应由“$”后跟数字或数值表达式来指定。未指定字段编号表达式计算为非负整数以外的任何值的效果;在此上下文中,未初始化的变量或字符串值不需要转换为数值

所以可能会有实现被破坏的情况。至少Brian Kernighan 自己的版本:

$ echo 1 2 | bawk '{print $b}'
bawk: illegal field $(), name "b"
 input record number 1, file 
 source line number 1

0在任何情况下,您都可以通过添加以下内容来强制在数字上下文中计算表达式:

$ echo 1 2 | awk '{print $(b+0)}'
1 2

相关内容