awk数组解释?

awk数组解释?

我是 awk 编程的新手,正在学习数组的工作原理。我找到了这段代码:

awk 'BEGIN{OFS=FS=","}NR==FNR{a[$1]=$2;next}$3 in a && $3 = a[$3]' filez filex

他们将$1其作为索引放入数组中,并$2作为值 then if$3等于索引 和 for this one $3 = a[$3]。我不明白这是什么意思,因为第一个文件只有 2 列 -$3与第二个文件相比,他们在哪里想到的$3?!?

输入文件filez

111,111
112,114
113,113

输入文件filex

A,bb,111,xxx,nnn
A,cc,112,yyy,nnn
A,dd,113,zzz,ppp

答案1

该脚本的目的是将第二个文件 ( ) 第三列中的值替换filex为第一个文件 ( ) 第二列中存储的相应值filez

NR是当前行相对于第一个处理的文件的第一行的行号。它是一个“全局”线路计数器。FNR是相对于当前处理的文件的开头的当前行号。
NR==FNR是仅对第一个文件计算为 true 的条件。相应的操作 ( {a[$1]=$2;next}) 将整个第一个文件逐行放入字典中,字典是a一个关联数组,其目的是根据第一列中的相应值查找第一个文件第二列的值。next使awk跳过剩余条件并重新开始循环,读取下一行。

$3 in a && $3 = a[$3]是具有潜在副作用的条件(分配给$3)。仅对第二个文件进行评估(当NR==FNR为 false 时;请记住,当NR==FNR为 true 时,$3 in a && $3 = a[$3]将被跳过)。对于每一行,如果在字典中找到第三个字段的值(作为索引)a,则将其替换为字典中的相应值。然后,如果$3 = a[$3]计算结果为 true,则打印该行(因为在 AWK 程序中,基本上由条件(或“模式”)-动作对组成,条件或动作都可以省略,省略的动作相当于print)。

假设这缩短了filez

111,111
112,114

filex

A,bb,111,xxx,nnn
A,cc,112,yyy,nnn

一步一步发生的事情是:

  1. filez读取的第一行;NR==FNR计算结果为1==1,真;因此,{a[$1]=$2;next}执行 ;a[111]设置为111next意味着$3 in a && $3 = a[$3]跳过此行脚本的其余部分(具体来说,$3暂时不使用);不打印任何内容,因为执行的操作不包含任何打印命令;

  2. filez读取第二行和最后一行;NR==FNR评估结果为2==2, true;{a[$1]=$2;next}被执行;a[112]被设定为114;$3 in a && $3 = a[$3]再次被跳过,因为next;再次,没有打印任何内容;

  3. filex读取第一行;NR==FNR计算结果为3==1, false;因此{a[$1]=$2;next}不是被处决;评估下一个条件:$3111且 是 的索引值a,因此$3 in a为 true 并$3 = a[$3]评估;它导致将a[111],即111,分配给$3;由于111既不是0空字符串,条件赋值也计算为 true 并打印当前行;

    A,bb,111,xxx,nnn
    
  4. filex读取第二行和最后一行;NR==FNR计算结果为4==2, false;因此{a[$1]=$2;next}不是被处决;评估下一个条件:$3112且 是 的索引值a,因此$3 in a为 true 并$3 = a[$3]评估;它导致将a[112],即114,分配给$3;由于114既不是0空字符串,条件赋值也计算为 true 并打印当前行。

    A,cc,114,yyy,nnn
    

答案2

  • BEGIN{OFS=FS=","}将输入和输出字段分隔符设置为,
  • NR==FNR仅适用于第一个文件。因此,对于第一个文件:
    • a[$1]=$2$1将其作为索引和$2值放入array 中a
    • next跳过该行脚本的其余部分。

再说一遍:next意思是脚本的其余部分仅针对第二个文件执行(以及第三个、第四个……文件,如果存在的话)。

  • $3 in a && $3 = a[$3]如果第三个字段是数组的键a,则将第三个字段替换为a[$3]。现在,由于这不是在操作环境中(即不在 inside {}),这意味着如果两个条件都为真,则应打印当前记录。否则,什么也不能做。

一般来说,由于右侧的条件是赋值,因此如果左侧为 true,则结果为 true。但是,如果分配了空字符串或数字 0,则该分配将被评估为 false。这可能是有意为之,但通常是程序员未能注意到的边缘情况。要查看它,请尝试使用 awk 代码

filez:

111,111
112,114
113,113
000,000

filex:

A,bb,111,xxx,nnn
A,cc,112,yyy,nnn
A,dd,113,zzz,ppp
A,ee,000,uuu,aaa

请注意,对于最后一行,虽然$3 in a为 true,但$3 = a[$3] 分配为 0,因此不会打印该行!

$ awk 'BEGIN{OFS=FS=","}NR==FNR{a[$1]=$2;next}$3 in a && $3 = a[$3]' filez filex
A,bb,111,xxx,nnn
A,cc,114,yyy,nnn
A,dd,113,zzz,ppp

应OP要求澄清:

请记住:该数组填充有a[$1]=$2 在第一个文件中, filez.
$3 = a[$3]被执行对于第二个文件, filex.
例如:在第二行fileza[$1]=$2-> a[112] = 114。在第二行filex$3 = a[$3]-> 112=a[112]=114

相关内容