从这个问题,我用这个解决方案回答:
awk 'FNR==NR{a[FNR]=$2;next}{$NF=a[FNR]}1' file2 file1
它按预期工作。
但我想到的第一个解决方案是:
$ awk 'FNR==NR{a[FNR]=$2;next}$NF=a[FNR]' file2 file1
A 63 9 6
B 45 3 5
它不起作用,因为什么时候awk
没有打印 中的第一行file1
。这让我很惊讶,不知道为什么awk
跳过第一行。
以下是一些示例:
$ awk 'FNR==NR{next}$1=123' file2 file1
123 23 8 T
123 63 9 9
123 45 3 J
$ awk 'FNR==NR{a[FNR]=$2;next} FNR in a' file2 file1
A 23 8 T
A 63 9 9
B 45 3 J
您可以看到,从这两个示例中,awk
都按预期工作。首先将新值分配给当前记录影响记录值的字段,并awk
打印新值。第二个显示awk
已经处理了 中的所有记录file2
,没有跳过任何记录。
为什么awk
要跳过我的第一个解决方案中的第一行?
我用过gawk 4.0.1
,也用过测试过mawk 1.3.3
。
答案1
你有:
$NF=a[FNR]
作为最终条件(决定是否打印的条件)。赋值返回分配的值,在本例中为a[FNR]
。链接问题的数据文件的第一行是:
A 0
a[FNR]
被初始化为$2
.这意味着a[FNR]
is的值0
,对于 awk 来说是一个假值。这意味着分配为假,这使得条件为假并抑制默认打印行为。如果我们将数据文件更改为:
A 1
A 6
B 0
那么第一行将被打印,但最后一行将丢失。
因此,并不是第一行缺失,而是最后一个字段为零(或空)的任何行。恰好第一行而且只有第一行是这样的。
答案2
经过一番研究,我找到了答案。
首先,根据这:
Expression Patterns
An expression pattern will be evaluated as if it were an expression in a
Boolean context. If the result is true, the pattern will be considered to
match, and the associated action (if any) will be executed. If the result is
false, the action will not be executed.
所以在我的例子中,$NF=a[FNR]
将被视为一种表达模式。正如文档所说,赋值的结果被评估为true
or false
。
在我的示例中,赋值的结果是0
,它在布尔上下文中计算为false
,导致模式被认为不匹配,不执行任何操作。
@Michael Homer 的注释
这是一个例子来表明The assignment to m returned the value assigned.
inawk
是不正确的。
$ awk 'function test() {a=2} BEGIN{print test()}'
<blank line>
$ perl -e 'sub test {$a=2}; print test'
2
awk
你可以看到,示例中返回了什么赋值?
awk 'n=(m=5);END{print n}' prints 5
因为副作用,这并不意味着awk
赋值返回值。