【问题标题】:awk - if values match then print file1 and file 2awk - 如果值匹配,则打印 file1 和 file 2
【发布时间】:2015-12-02 13:48:53
【问题描述】:

我用谷歌搜索了很多我的问题并测试了不同的解决方案,但似乎没有一个有效。我什至提前成功使用了相同的命令,但现在我无法获得所需的输出。

我有文件 1

AAA;123456789A
BBB;123456789B
CCC;123456789C

还有文件2

1;2;3;CCC;pippo
1;2;3;AAA;pippo
1;2;3;BBB;pippo
1;2;3;*;pippo

我想要的输出是这样的:

1;2;3;CCC;pippo;CCC;123456789C
1;2;3;AAA;pippo;AAA;123456789A
1;2;3;BBB;pippo;BBB;123456789B

我试过这个命令:

awk -F";" -v OFS=";" 'FNR == NR {a[$10]=$1; b[$20]=$2; next}($10 in a){ if(match(a[$10],$4)) print $0,a[$10],b[$20]}' file1 file2

但我得到了这个输出(只有一个条目,即使文件更大):

1;2;3;CCC;pippo;CCC;123456789C

我做错了什么?如果它管理一个它应该为所有其他。为什么这没有发生? 另外为什么如果我设置a[$1]=$1 它不起作用?
谢谢你的帮忙! 如果可能的话,你能解释一下答案吗?所以下次我就不用求助了!

编辑:对不起,我没有提到(因为我想让示例保持最小)在 file2 中的某些字段只是“*”。我想添加一个“其他不匹配做某事”。

【问题讨论】:

  • 所以你想匹配 file1 中的第一个字段和 file2 中的第四个字段?另外,如果只有 5 个或 6 个字段,为什么要获取字段 $10$20
  • arr 未定义。
  • @CasimiretHippolyte 这是一个错字,arr 应该是 a 。 @fedorqui 我只是习惯了大于 4 的值。但是为什么我不能使用数组 a 的 $1 和 $2 呢?不是空的吗?
  • @EdMorton 你得到了我做错的地方。如何从 file1 传递整个 col1 并将其与文件 2 的 col4 进行比较?我从这里修改了我的代码*.com/questions/31168521/…
  • 获取 Arnold Robbins 所著的《Effective Awk Programming, 4th Edition》一书。您需要对 awk 作为基础有一个基本的了解,而不仅仅是复制/粘贴脚本并尝试随机更改以希望它能起作用。

标签: regex awk merge match multiple-columns


【解决方案1】:

求救!

$ awk 'BEGIN{FS=OFS=";"} 
     NR==FNR{a[$1]=$0;next} 
            {print $0,a[$4]}' file1 file2

1;2;3;CCC;pippo;CCC;123456789C
1;2;3;AAA;pippo;AAA;123456789A
1;2;3;BBB;pippo;BBB;123456789B

更新: 根据原始输入文件,它只是在寻找完全匹配。如果要跳过不匹配的条目,则需要使用$4 in a 限定打印块

$ awk 'BEGIN{FS=OFS=";"} 
     NR==FNR{a[$1]=$0;next} 
     $4 in a{print $0,a[$4]}' file1 file2

【讨论】:

  • 似乎完美运行!非常感谢!你能温和地告诉我为什么你不需要使用if(match()) 吗?
  • 我回答后输入文件发生了变化。
【解决方案2】:

join 是为这个 sort 制作的:

$ join -t';' -1 4 -o1.{1..5} -o2.{1..2} <(sort -t';' -k4 file2) <(sort -t';' file1)

1;2;3;AAA;pippo;AAA;123456789A
1;2;3;BBB;pippo;BBB;123456789B
1;2;3;CCC;pippo;CCC;123456789C

输出是您要求的,除了行的顺序,我认为这并不重要。需要join-o 选项,因为您需要完整的字段集;您可以尝试省略它,而您将获得左侧的连接字段,这也可能没问题。

【讨论】:

  • 不错!不幸的是,正如我在编辑中提到的那样,它在示例中完美运行,但不适用于我的真实文件。对不起,我忘了解释一块。