我是 awk 编程的新手,我正在学习数组的工作原理。我找到了这个代码:
awk 'BEGIN{OFS=FS=","}NR==FNR{a[$1]=$2;next}$3 in a && $3 = a[$3]' filez filex
Run Code Online (Sandbox Code Playgroud)
他们将$1
作为索引放入数组并$2
作为值然后如果$3
等于一个索引并且为这个$3 = a[$3]
。我不明白这是什么意思,因为第一个文件只有 2 列——与第二个文件$3
相比,他们是$3
从哪里想出的?!?
输入文件filez
:
111,111
112,114
113,113
Run Code Online (Sandbox Code Playgroud)
输入文件filex
:
A,bb,111,xxx,nnn
A,cc,112,yyy,nnn
A,dd,113,zzz,ppp
Run Code Online (Sandbox Code Playgroud)
此脚本的目的是将第二个文件 ( filex
)的第三列中的值替换为存储在第一个文件 ( filez
)的第二列中的相应值。
NR
是当前行相对于第一个处理文件的第一行的编号。它是一个“全局”行计数器。FNR
是当前行相对于当前处理文件的开头的行号。
NR==FNR
是仅对第一个文件评估为真的条件。相应的操作 ( {a[$1]=$2;next}
) 将整个第一个文件逐行放入a
字典中,这是一个关联数组,其目的是根据第一列中的相应值查找第一个文件第二列的值。next
使awk
跳过剩余的条件并重新开始一个循环,阅读下一行。
$3 in a && $3 = a[$3]
是具有潜在副作用的条件(分配给$3
)。它仅针对第二个文件进行评估(whenNR==FNR
为假;请记住,whenNR==FNR
为真,$3 in a && $3 = a[$3]
被跳过)。对于每一行,如果在a
字典中找到第三个字段的值(作为索引),则将其替换为字典中的相应值。然后,如果$3 = a[$3]
评估为真,则打印该行(因为在 AWK 程序中,基本上由条件(或“模式”)-动作对组成,条件或动作都可以省略,省略的动作相当于print
)。
假设这缩短了filez
:
111,111
112,114
Run Code Online (Sandbox Code Playgroud)
和filex
:
A,bb,111,xxx,nnn
A,cc,112,yyy,nnn
Run Code Online (Sandbox Code Playgroud)
逐步发生的是:
filez
读取第一行;NR==FNR
评估为1==1
,真;因此,{a[$1]=$2;next}
被执行;a[111]
设置为111
;next
意味着$3 in a && $3 = a[$3]
该行跳过脚本的其余部分 ( )(具体来说,$3
现在不使用);不打印任何内容,因为执行的操作不包含任何打印命令;
filez
读取第二行和最后一行;NR==FNR
评估为2==2
,真;{a[$1]=$2;next}
被执行;a[112]
设置为114
;$3 in a && $3 = a[$3]
再次被跳过,因为next
; 同样,没有打印任何内容;
filex
读取第一行;NR==FNR
评估为3==1
,假;因而{a[$1]=$2;next}
是不执行; 评估下一个条件:$3
是111
并且是 的索引值a
,因此$3 in a
为真并被$3 = a[$3]
评估;它导致 的分配a[111]
,即111
,$3
;由于111
不是0
也不是空字符串,条件赋值也评估为真并打印当前行;
A,bb,111,xxx,nnn
Run Code Online (Sandbox Code Playgroud)
filex
读取第二行和最后一行;NR==FNR
评估为4==2
,假;因而{a[$1]=$2;next}
是不执行; 评估下一个条件:$3
是112
并且是 的索引值a
,因此$3 in a
为真并被$3 = a[$3]
评估;它导致 的分配a[112]
,即114
,$3
;由于114
不是0
也不是空字符串,条件赋值也评估为真,并打印当前行。
A,cc,114,yyy,nnn
Run Code Online (Sandbox Code Playgroud)