【问题标题】:How to extract only first line that matches each pattern from a file?如何仅从文件中提取与每个模式匹配的第一行?
【发布时间】:2018-05-10 13:01:38
【问题描述】:

我有一个看起来像

的文本文件
Line_A 123
Line_A 456
Line_A 789
Line_B 123
Line_B 456
Line_B 789
Line_C 123
Line_C 456
Line_C 789

还有一个如下所示的参考文件:

 Line_A
 Line_B
 Line_C

我想从文本文件中提取与参考文件中每个名称匹配的第一行,如下所示:

Line_A 123
Line_B 123
Line_C 123

到目前为止,我只能从第一场比赛中得到第一行:

grep -A1 -w -f  reference.txt -m 1 file.txt

也许我需要一个 for 循环? TIA

【问题讨论】:

    标签: awk sed grep


    【解决方案1】:

    另一个awk

    $ awk 'NR==FNR{a[$1];next} $1 in a{delete a[$1]; print}' reference file
    

    将引用保留在一个集合中,当在文件中看到时打印该行并删除引用,因此只会打印第一个实例。

    【讨论】:

      【解决方案2】:

      又一个 awk:

      $ awk 'a[$1]++==1' ref file
      Line_A 123
      Line_B 123
      Line_C 123
      

      按上述顺序读取两个文件,计算第一列中的每个字符串,并在第二次看到时打印。如果file 中有不在reference 中的字符串,这将失败。在这种情况下,请使用其他解决方案之一。

      【讨论】:

      • 智能+1。如果引用中有重复,也会失败。
      【解决方案3】:

      只要在参数列表中首先列出参考文件,您就可以在 Awk 中对文件进行一次遍历:

      awk 'FNR == NR { name[$1] = 0; }
           FNR != NR { for (i in name) if ($0 ~ i && name[i]++ == 0) { print $0; break; } }' \
          reference.txt file.txt
      

      使用样本输入,这将产生所需的输出。

      这是 Awk 中相当标准的技术。您使用FNR == NR 条件读取第一个文件(文件行号等于总行号;仅适用于第一个文件中的行)并保存适当的信息以供以后使用。通常,人们在第一行使用next;有用。这意味着他们可以避免 FNR != NR 条件——我喜欢它的对称性。

      在处理第二个和后续文件时,检查从第一个文件中读取的每个名称是否与一行匹配,并且该名称之前没有打印过,如果没有处理,则打印该行。如果当前名称匹配,则 break 会避免检查其他名称。

      这是许多人编写命令的方式;它也有效。

      awk 'FNR == NR { name[$1] = 0; next }
           { for (i in name) if ($0 ~ i && name[i]++ == 0) { print $0; break; } }' \
          reference.txt file.txt
      

      这两个版本的代码都在行中的任意位置查找名称;如果您严格要匹配第二个(或后续)文件的$1,您可以更改条件(实际上,简化它们)。并且karakfashows 在匹配时删除匹配项(而不是增加计数器),这对性能更好,因为您不必继续匹配不再相关的匹配项。但是,此处显示的代码更容易适应显示给定名称的第二个、第三个或最后一个条目(处理第二个或第三个涉及将 0 更改为 1 或 2;处理“最后一个”需要进行更多实质性更改)。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2017-02-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-12-15
        • 1970-01-01
        相关资源
        最近更新 更多