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:使用两个匹配条件的文件和计数相等的唯一标识符的主要内容,如果未能解决你的问题,请参考以下文章

如果条件唯一,则 MySQL 不同计数

使用 awk sub 以数字方式为字符串添加前缀而不更改计数状态最多 5 个匹配“在每行具有多个匹配项的文本文件中”

awk / sed:如果任何字段与模式匹配,则替换所有字段

如果条件唯一,MySQL独特计数

匹配 AWK 中多行的正则表达式。 && 操作员?

awk