【问题标题】:Compare two columns in different files and append data for the shared items - UNIX比较不同文件中的两列并为共享项附加数据 - UNIX
【发布时间】:2014-06-24 07:33:48
【问题描述】:

我一直在论坛中寻找我的问题的解决方案,但不幸的是我没有成功。我很喜欢 bash;因此,我真的很感激任何建议链接到以前的问题/讨论

我有两个文件:

文件1

    Ada     ada
    Ada     ada
    Ada     aidB
    Ada     alkA
    Ada     alkB
    Ada     alkB
    AdiY    adiA
    AdiY    gadA

文件2

    NP_414557.1     insL1
    NP_414559.1     mokC
    YP_025292.1     hokC
    NP_414560.1     nhaA
    NP_414561.1     nhaR
    NP_414562.1     insB1
    NP_414563.1     insA
    NP_414564.1     rpsT

我想根据第二列比较 file1file2。如果对象相同,我想将 file2 中第 1 列中的文本附加到 file1 中第三列中的特定共享条目。

预期输出: 文件1

    PhoB  caiT  NP_414580.1     
    PhoP  caiE  NP_414581.1     
    PhoP  caiB  NP_414582.1 

请把报告的文字当作例子。

我在 awk 中苦苦挣扎,试图从之前的问题中调整代码:

Compare two files of different columns and print different columns

awk 'NR==FNR{a[$1]=$2 ; next }$2 in a {$1=$1 FS a[$2]print}' file1 file2

非常感谢您的宝贵时间和帮助。

最好的。

【问题讨论】:

  • 您的示例输入看起来有点被截断。 caiT 来自哪里?
  • 您的file1file2 似乎完全没有共同点,您提出的输出与它们中的任何一个都没有共同点。考虑发布一些示例数据,这些示例数据至少有最小的机会展示您所询问的内容......
  • 您好,谢谢您的回答。正如我写的那样,我报告的数据只是示例。第二列 file1file2 和输出具有相同种类的信息。试想一下,PhoB 和 caiT 将出现在 file1 中,caiT 和 NP_414508.1 出现在 file2 中。我希望这能让它更清楚。
  • 如果你能解释一下代码就好了。谢谢。

标签: bash unix awk


【解决方案1】:

正如@fedorqui 评论的那样,您的示例输入/输出不一致。我认为这应该可以解决问题:

awk 'NR==FNR{a[$2]=$0; next} a[$2]>0{print a[$2],$1}' file1 file2

文件1:

A alice
B bob
C carol
D dan

文件2:

1 dan
2 alice
3 carol
4 bob

输出:

$ awk 'NR==FNR{a[$2]=$0} NR>FNR && a[$2]>0{print a[$2],$1}' file1 file2
D dan 1
A alice 2
C carol 3
B bob 4

输出可以按您使用sort -k 选择的任何列进行排序。分解awk 代码:

  • NR==FNR{a[$2]=$0; next} - NR 是一个 awk 变量,其中包含到目前为止处理的总行数。 FNR 类似,但仅包含当前文件的进程行数,因此该条件实际上意味着“仅对第一个输入文件执行此操作”。关联操作将整行 ($0) 存储在关联数组 a 中,索引是该行的第二个字段的值。 next 只是表示awk 应该移动到下一行而不做进一步处理。

  • a[$2]>0{print a[$2],$1} - 此条件仅针对第二个和后续输入文件进行测试。第二个字段用作从a 中查找值的索引 - 如果该值大于 0(即在本例中为字符串),则打印该值,然后是第一个字段当前行。

基本上,第一个文件的每一行都存储在一个数组中,由该行的第二个字段索引。如果第二个字段在第二个文件中匹配,则打印第一个文件中的整行,并附加第二个文件中的第二个字段。

【讨论】:

  • 嗨乔希,非常感谢您的回答!对不起,如果我的例子不一致。无论如何,你完全正确。
  • 我尝试了你的建议,只是在更改文件名后复制和粘贴你的代码(实际上你建议了两个不同的代码,我都试过了)。不幸的是,我没有任何输出。知道为什么吗?再次感谢您!
  • 亲爱的乔希,你完全正确!您的脚本完成了这项工作!我创建了两个测试文件,并使用它们获得了正确的输出。但是,使用我的真实文件脚本不起作用。我控制了我的文件,它们是制表符分隔的。不过,显然格式有问题。知道如何检查吗?再次感谢您的帮助!
  • 请参阅stackoverflow.com/questions/5374239/tab-separated-values-in-awk 以获取使用awk 与制表符分隔文件的帮助。确保您的文件具有 Unix 行结尾而不是 DOS 行结尾也是值得的 - 在它们上尝试 dos2unix
  • 好的!我更正了文件,看起来效果很好!太感谢了!只是为了更多地了解awk,你能写一个代码的小解释吗?再次感谢!
【解决方案2】:

您可以使用 join 命令来链接文件上的字段。 最简单的使用方法可以是:

 join -j 2

要获得第一个文件的第一个和第二个文件的输出,并在第二个文件的第一个字段之后,您可以使用 -o 选项,如下所示:

 join -j 2 -o 1.1 1.2 2.1

要求两个文件中的行在第二个字段中排序,如果行没有正确排序,您可以使用以下 bash 技巧:

 join -j 2  -o 1.1 1.2 2.1 <(sort -k2 1) <(sort -k2 2)

假设这是两个文件的内容:

 $ cat 1
 FIRST   first
 SECOND  second
 THIRD   third
 FOURTH  fourth
 $ cat 2
 2       second
 1       first
 3       third
 4       fourth

注意:每行的字段分隔符是TAB字符

最终结果:

 $ join -j 2 -o 1.1 1.2 2.1 <(sort 1) <(sort -k2 2)
 FIRST first 1
 FOURTH fourth 4
 SECOND second 2
 THIRD third 3

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-05-10
    • 1970-01-01
    • 2011-11-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-09
    相关资源
    最近更新 更多