在两个公共字段上连接两个文件

在两个公共字段上连接两个文件

我有两个文件

file1.txt

78Z|033333157|0000001|PERD1|2150421|D|0507020|3333333311
78Z|033333157|0000001|PERD0|2160208|A|1900460|3333333311
78Z|033333157|0000001|RSAB1|2150421|D|0507070|3333333311
78Z|033333157|0000001|RSAB0|2160208|A|1900460|3333333311
78Z|033333157|0000001|ANT37|2141023|D|1245260|3333333311
78Z|033333157|0000001|ANT36|2150422|D|1518490|3333333311
78Z|033333157|0000001|ANT28|2150321|D|0502090|3333333311
78Z|033333157|0000001|ANT27|2150122|D|0501450|3333333311
78Z|033333157|0000001|ANT26|2141222|D|1637460|3333333311
78Z|033333157|0000001|ANT10|2160208|A|1900460|3333333311
78Z|033333157|0000001|ABS10|2151221|D|1223390|3333333311
78Z|696931836|0000001|PERD0|2160203|A|1114450|2222222222
78Z|696931836|0000001|RSAB0|2160203|A|1114450|2222222222
78Z|696931836|0000001|ANT09|2160203|A|1114450|2222222222
78Z|010041586|0000001|PERD0|2160119|A|1835100|3333333333
78Z|010041586|0000001|RSAB0|2160119|A|1835100|3333333333
78Z|010041586|0000001|ANT33|2160119|A|1835100|3333333333
78Z|011512345|0000001|PERD0|2151213|A|1413550|4444444444
78Z|011512345|0000001|RSAB0|2151213|A|1413550|4444444444
78Z|011512345|0000001|ANT32|2160219|A|0319230|4444444444
78Z|011512345|0000001|ANT09|2160218|D|0319230|4444444444
78Z|011512345|0000001|ANT07|2150729|D|1508230|4444444444
78Z|011512345|0000001|ANT06|2141013|D|1208190|4444444444
78Z|011512345|0000001|ABB06|2131224|D|1857030|4444444444
78Z|012344052|0000001|PERD0|2160203|A|1219570|5555555555
78Z|012344052|0000001|ANT50|2160203|A|1219570|5555555555
78Z|099999999|0000001|PERD0|2151214|A|1512460|6666666666
78Z|099999999|0000001|RSAB0|2151214|A|1512460|6666666666
78Z|099999999|0000001|ANT32|2160219|A|0319000|6666666666
78Z|099999999|0000001|ANT09|2160218|D|0319000|6666666666
78Z|099999999|0000001|ABS10|2150615|D|0125350|6666666666

file2.txt

3333333311|ANT10
2222222222|ANT09
5555555555|ANT50
3333333333|ANT33
6666666666|ANT32
4444444444|ANT09

我需要创建一个新文件,其中的行与第四列和第八列以及file1.txt第二列和第一列相匹配file2.txt

结果一定是(顺序不重要)

file3.txt

78Z|033333157|0000001|ANT10|2160208|A|1900460|3333333311
78Z|696931836|0000001|ANT09|2160203|A|1114450|2222222222
78Z|012344052|0000001|ANT50|2160203|A|1219570|5555555555
78Z|010041586|0000001|ANT33|2160119|A|1835100|3333333333
78Z|099999999|0000001|ANT32|2160219|A|0319000|6666666666
78Z|011512345|0000001|ANT09|2160218|D|0319230|4444444444

答案1

awk -F'|' 'NR==FNR{e[$2$1]=1;next};e[$4$8]' file2.txt file1.txt

初读文件2e[field2+field1]然后设置数组文件1并打印是否e[field4+field8]已设置。

或者翻转字段:

awk -F'|' 'NR==FNR{e[$1$2]=1;next};e[$8$4]' file2.txt file1.txt

答案2

问题已标记,但我认为值得注意的是你不用于awk执行此操作。 coreutils 有一个join实用程序对于此类事情很有用,尽管对于您的数据来说有点麻烦。

我假设你的 shell 是 bash 和 GNU coreutils。这可以通过其他风格来完成,但可能需要对数据进行更多的前/后处理。

无需再费周折:

join -t"|" -14 -22 -o"$(echo 1.{1..8} 2.1)" \
  <(sort -t"|" -k4 file1.txt) \
  <(sort -t"|" -k2 file2.txt) \
  | grep -Po ".*([\d]+)(?=\|\1$)"

join-1接受两个输入文件并将它们连接到通过和参数传递的字段上-2-t指示输入文件中的自定义字段分隔符。 join要求输入文件按照要连接的字段进行排序,因此两个输入文件在传递到 之前在进程替换中进行排序join。该-o参数指定如何输出字段。默认情况下是连接字段,后面是文件 1 的非连接字段,最后是文件 2 的非连接字段,因此我们需要指定要按顺序排列文件 1 的所有字段,然后是文件 2 的字段 1。

您还要求联接位于 file1 的字段 8 和 file1 的字段 1 上。当连接输出字段 8 和 9 相同时,通过 grep 查找行来简单地实现这一点。使用正则表达式前瞻grep -Po允许我们做到这一点并有效删除字段 9 以提供所需的输出。输出是:

78Z|696931836|0000001|ANT09|2160203|A|1114450|2222222222
78Z|011512345|0000001|ANT09|2160218|D|0319230|4444444444
78Z|033333157|0000001|ANT10|2160208|A|1900460|3333333311
78Z|099999999|0000001|ANT32|2160219|A|0319000|6666666666
78Z|010041586|0000001|ANT33|2160119|A|1835100|3333333333
78Z|012344052|0000001|ANT50|2160203|A|1219570|5555555555

答案3

更简单,假设在 file2 中不允许两次给出相同的第一个字段:

awk -F'|' 'FNR == NR { key[$1] = $2; next } $8 in key && key[$8] == $4' file2.txt file1.txt

答案4

尝试

awk 'BEGIN { FS="|"}
     FNR == NR { key[$2 $1]=NR }
     FNR > NR { k=$3 $8 ;if (k in key)  print ;} ' file2.txt file1.txt

在哪里

  • BEGIN { FS="|"}告诉 aw 用作分隔符(您可以在命令行上|使用)-F\|
  • FNR == NR { key[$2 $1]=NR }记住文件中的密钥(在 file2.txt 中时)
  • FNR > NR { k=$4 $8 ;if (k in key) print ;}如果键在哈希列表中,则打印它

编辑:您提到第三个字段并加入第四个字段。

相关内容