AWK:使用两个匹配条件的文件和计数相等的唯一标识符
Posted
技术标签:
【中文标题】AWK:使用两个匹配条件的文件和计数相等的唯一标识符【英文标题】:AWK: Equal unique identifier using two file and count that match criteria 【发布时间】:2022-01-19 13:32:54 【问题描述】:我正在处理与两个文件中的帐号匹配的两个数据。 并有一个条件或条件与第二个文件中的值和与条件匹配的计数。
第一个文件是定长的,帐号是从1到8:
68541561 12531563 20211205154331……NN061
68541562 12531563 20211205154332……NN061
68541563 12531563 20211205154333……NN000
68541564 12531563 20211205154334……NN061
68541565 12531563 20211205154335……NN000
68541566 12531563 20211205154336……NN061
第二个文件以逗号分隔,结构类似于定义文件但有重复记录。
68541561,Customer Proc 1
68541565,Answer
68541561,Customer Proc 1
68541562,Customer Proc 1
68541561,Customer Proc 1
68541563,Answer
68541562,Customer Proc 1
68541564,Customer Proc 1
68541565,Answer
68541564,Customer Proc 1
68541565,Answer
68541561,Customer Proc 1
68541562,Customer Proc 1
68541563,Answer
预期输出,它将从第一个文件中添加计数:
68541561 12531563 20211205154331……NN0614
68541562 12531563 20211205154332……NN0613
68541563 12531563 20211205154333……NN0002
68541564 12531563 20211205154334……NN0612
68541565 12531563 20211205154335……NN0003
68541566 12531563 20211205154336……NN0610
我确实有正在运行的脚本,但它只显示计数 1,它似乎只读取了第一个文件。
awk -f test.awk pass=0 testfile2.dat pass=1 testfile.txt
BEGIN
pass==0
ACT=substr($1)
RES[ACT]=$2
pass==1
FS=","
ACT=substr($0,1,8)
##LIST[ACT]=RESCODE
LIST[ACT]=ACT
if((RES[ACT]=="Customer Proc 1")) OTHCUST1++
if((RES[ACT]=="Customer Proc 2")) OTHCUST2++
if((RES[ACT]=="Customer Proc 3")) OTHCUST3++
if((RES[ACT]=="Customer Proc 4")) OTHCUST4++
if((RES[ACT]=="Answer")) OTHANSW++
if((RES[ACT]=="Busy")) OTHBUSY++
if((RES[ACT]=="Hang Up")) OTHAM++
END
for (nmb in LIST)
printf "%1378s|", $0 >> "OUTFILE"
printf "%s", OTHCUST1 >> "OUTFILE"
printf "%s", OTHCUST2 >> "OUTFILE"
printf "%s", OTHCUST3 >> "OUTFILE"
printf "%s", OTHCUST4 >> "OUTFILE"
printf "%s", OTHANSW >> "OUTFILE"
printf "%s", OTHBUSY >> "OUTFILE"
printf "%s", OTHAM >> "OUTFILE"
【问题讨论】:
该脚本无法运行,因为它在substr($1)
处存在语法错误。它似乎也与您描述的问题完全无关。最后 - 不要使用所有大写的变量名,以避免与内置变量名发生冲突,并使您的代码在使用/不使用内置变量的位置更清晰。
您说First file is fixed-length, the account number is from 1 to 8
,但随后您显示示例输入,其中帐号始终只是第一个以空格分隔的字段。如果它不仅仅是第一个以空格分隔的字段,那么请在您的输入中包含该字段的示例,否则关于它的固定宽度和前 8 个字符的内容只会混淆问题并导致比必要的更复杂的解决方案(具有使用substr($0,1,8)
而不仅仅是$1
)。
知道了。我只是想在条件下移植我当前的 awk 脚本。但基本上我可以使用不同的 awk 脚本来避免这种情况的复杂性。
但是,当您寻求解决问题的帮助时,您应该创建并发布 minimal reproducible example,其中包含简洁地演示只是该问题的示例代码,而不是抛出无论您使用什么代码,这就像要求您的机械师修理您的汽车但向他们展示您的马一样。见How to Ask。
【参考方案1】:
你的问题并不完全清楚,但我认为这就是你想要做的:
$ awk -F'[,[:space:]]+' 'NR==FNRcnt[$1]++; next print $0 cnt[$1]+0' file2 file1
68541561 12531563 20211205154331……NN0614
68541562 12531563 20211205154332……NN0613
68541563 12531563 20211205154333……NN0002
68541564 12531563 20211205154334……NN0612
68541565 12531563 20211205154335……NN0003
68541566 12531563 20211205154336……NN0610
顺便说一句,您在发布的代码中执行 FS=","
的位置为时已晚 - 输入的第一行已被读取并在读取该行之前拆分为字段。实现它的一种方法是将 FS=","
更改为 if (FNR==1) FS=","; $0=$0
以在设置 FS 后让 awk 重新拆分记录,但这效率低下,所以我将它包装在 if
中,只在第一次这样做之后读取的行 FS
现在设置在读取第二行和后续行之前。
您的代码中的所有printf "%s"
s 都应该是printf "%d"
s 顺便说一句,否则当设置计数变量的条件未命中时,您将得到空字符串而不是打印零。
【讨论】:
【参考方案2】:使用您展示的示例,请尝试关注awk
代码。
awk '
FNR==NR
arr[$1]++
next
($1 in arr)
print $0 arr[$1]
delete arr[$1]
' FS="," file2 FS=" " file1
说明:为上述代码添加详细说明。
awk ' ##Starting awk program from here.
FNR==NR ##Checking condition which will be TRUE when file2 is being read.
arr[$1]++ ##Creating array with name arr with index of $1.
next ##next will skip statements from here.
($1 in arr) ##Checking condition if $1 is present in arr.
print $0 arr[$1] ##printing current line here with arr[$1].
delete arr[$1] ##Deleting arr entry with $1 here.
' FS="," file2 FS=" " file1 ##Set FS as comma for file2 and space for file1 and pass Input_files too here.
【讨论】:
以上是关于AWK:使用两个匹配条件的文件和计数相等的唯一标识符的主要内容,如果未能解决你的问题,请参考以下文章