awk 中大括号内赋值与大括号外赋值

awk 中大括号内赋值与大括号外赋值

这个问题,我用这个解决方案回答:

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]将被视为一种表达模式。正如文档所说,赋值的结果被评估为trueor 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赋值返回值。

相关内容