【问题标题】:Fetching rows from file_1 based on another file_2根据另一个 file_2 从 file_1 获取行
【发布时间】:2016-11-12 19:13:03
【问题描述】:

我有一个制表符分隔的文本文件,如下所示:

文件_1:

A1  13f  Jos  +
B1  zh4  Kia  -
C2  nh2  Met  -
D3  5gh  Lox  +
F4  w4t  Nit  -

文件_2

N3  6jg  Jut -
J8  76d  Met +
A1  99g  Kia -
M6  45k  Qox +
V2  87h  Nit -

我想从 file_1 中提取条目,其中第 3 列条目与 file_2 的第 3 列条目匹配,如下所示:

    B1  zh4  Kia -   
    C2  nh2  Met -    
    F4  w4t  Nit -

comm-12 file_1.txt file_2.txt 会帮忙吗?请指导我

【问题讨论】:

  • 我不明白。第一行来自文件 2,但第 2 行和第 3 行来自文件 1。
  • @choroba 我已经编辑了这个问题。很抱歉给您带来不便。
  • 'kia' 的行不能排在“Met”之前。对输出行的顺序有要求吗?

标签: linux awk file-comparison


【解决方案1】:

awk 在这里可能是最简单的(这保留了file_1 输入顺序):

$ awk 'NR==FNR { seen[$3]++; next } seen[$3]' file_2 file_1

B1  zh4  Kia  -
C2  nh2  Met  -
F4  w4t  Nit  -
  • 模式 NR==FNR 仅匹配第一个输入文件 (file_2) 中的行,并使用操作 { seen[$3]++; next } 构建所有第三列值的关联数组

    • seen[$3]++ 是构造包含唯一字段值集的关联的常用习惯用法:访问数组 seen 中的键 $3(第三个字段的值)隐式创建一个条目在第一次访问时键入键,而后增量 ++ 为条目提供一个非零值,该值在布尔上下文中计算为真(下面讨论的模式利用了这一点)。
  • 由于上一个操作中的next,模式seen[$3] 仅对第二个输入文件(file_1)执行,并且仅当第二个文件的第三列值也是出现在第一个文件中。计算结果为 true 的模式会隐式打印手头的行。

【讨论】:

  • +1 以获得出色的答案。虽然我对订单有疑问。这将在“Met”之前打印“Kia”...有没有办法让订单按照 file2 中的顺序进行。问题在“Kia”之前显示“Met”
  • 谢谢,@JayRajput。我曾假设 OP 的真正意图是保留 file_1 输入顺序,尽管最初的样本输出不一致(此后 OP 已更正)。
  • 是的。看到了...现在等待 OP 接受您的回答。
【解决方案2】:

comm 期望文件按要比较的列排序,并且其参数之前的空格不是可选的。

但是您可以使用cut 提取文件1 的第三列,如果它们不能出现在任何其他列中,则使用grep 从文件2 中提取该值:

cut -f3 file_1 | grep -Ff- file_2

不过,行的顺序对应于 file2。

B1      zh4     Kia     -
C2      nh2     Met     -
F4      w4t     Nit     -

为了获得正确的顺序,我会使用 Perl:

perl -e 'until (eof) {
             @F = split " ", <>;
             $h{ $F[2] } = 1;
         }
         while (<>) {
             @F = split " ";
             print if $h{ $F[2] };
         }' file_1 file_2

它首先将 file_1 的第三列 ($F[2]) 值存储到哈希 %h 中,然后遍历 file_2 并检查是否在哈希中设置了列 3 的值。

【讨论】:

    【解决方案3】:

    awk 答案。这对于小文件是可以的。对于大文件,看到的数组会变得很大,因为整行 $0 保存在数组中。

    awk 'NR==FNR { seen[$3] = $0; next} $3 in seen {print seen[$3]}' file_2 file_1
    

    输出

    A1  99g  Kia -
    J8  76d  Met +
    V2  87h  Nit -
    

    【讨论】:

    • 这是一个有趣的变化,但请注意,它只有在file_2 的第 3 列中没有重复项时才有效;否则,您将丢失输出行。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多