对于一个简单的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 未指定该行为)。无论如何,print
和print $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