首页 > 解决方案 > 匹配两个文件并使用 awk 根据第二个文件打印匹配的字符串

问题描述

我在下面有两个名为 InputFile 和 Ref 的文件

输入文件

1234~code1=yyy:code2=fff:code3=vvv
1256~code2=ttt:code1=yyy:code4=zzz
4567~code4=uuu
8907~code8=ooo:code7=rrr

参考

code2
code3
code8
code7

我必须将 Ref 中的所有记录匹配到 InputFile 的第二列(~ 分隔并将由冒号(:) 分割)。如果在 InputFile 中找到 Ref 中的记录,则应在 = 符号后打印前面的值,否则打印无。

期望的输出

1234~fff~vvv~~
1256~ttt~~~
4567~~~~
8907~~~ooo~rrr

我即将将其加载到以 Ref 记录为列的表中。

这是我的脚本:

awk '
BEGIN{
  FS=OFS="~"
}
FNR==NR{
  a[$0]
  next
}
FNR==1 && FNR!=NR{
  print
  next
}
{
  num=split($2,array,"[=:]")
  for(i=1;i<=num;i+=2){
    if(array[i] in a){
      val=val?val OFS array[i+1]:array[i+1]
    }
    else{
      val=val?val OFS "~":"~"
    }
  }
  print $1,val
  val=""
}
' Ref InputFile

它在 Ref 中存在的 InputFile 中打印数组(code1、code2 等),但它不按 Ref 的顺序打印。

脚本的输出

1234~~fff~vvv
1256~ttt
4567~
8907~ooo~rrr

标签: shellawk

解决方案


$ cat tst.awk
BEGIN {
    FS  = "[~:=]"
    OFS = "~"
}
NR == FNR {
    refs[++numRefs] = $0
    next
}
{
    delete ref2val
    for (fldNr=2; fldNr<NF; fldNr+=2) {
        ref2val[$fldNr] = $(fldNr+1)
    }

    printf "%s%s", $1, OFS
    for (refNr=1; refNr<=numRefs; refNr++) {
        ref = refs[refNr]
        printf "%s%s", ref2val[ref], (refNr<numRefs ? OFS : ORS)
    }
}

$ awk -f tst.awk refs file
1234~fff~vvv~~
1256~ttt~~~
4567~~~~
8907~~~ooo~rrr

推荐阅读