【问题标题】:grep, sed or awk to compare content of two filesgrep、sed 或 awk 比较两个文件的内容
【发布时间】:2013-01-28 14:13:05
【问题描述】:

我尝试在 bash 中解决以下问题。我有两个不同的文件(file1、file2),其中包含如下信息列表:

HWI-1KL104:145:C18ANACXX:5:1101:1168:2164   4   *   0   0   *   *   0   0   GTGCCTGAACTGGATGCATNGACAATGGGGAACATTACATATATAATACAAGGGAAACTCAAACGTTTCCNNNNNCAAGTATTTGACAGNNNNNNNNNNNN   @B@DDFFFHHHHHIHIJIJ#3AFGHHJJJJIIJJIJIIIJJJJJJJGIIJIJJJIJIJJJJIJJI=@EED#####,,5=;ADDFEEDDD############

显示的字符串代表单行。这意味着如果我这样做:

grep "HWI-1KL104:145:C18ANACXX:5:1101:1168:2164" file1

我的输出是上面的字符串。 HWI-1KL104:145:C18ANACXX:5:1101:1168:2164代表我的线路ID

您必须想象具有不同 ID 的数百万行这样的行(约 8GB 的​​ txt 文件)

我要做的是:

  1. 搜索 file1 中存在且 file2 中存在的那些 ID

  2. 将 file2 中匹配的行保存到仅包含 ID + 以下信息的新文件中:

HWI-1KL104:145:C18ANACXX:5:1101:1196:2120 CCCCTTCTCCAGGGGACCANGTATGTTTCTCTTATGGTCCTCCTTGTTTACTAGCTTCTCTGGCAGTGAGATTGTAGGCTGGTAATCCTTTACTCNNTNNN CCCFFFFFHHHHHJJJJJJ#4CDEEDCDDDDDC######

所以,丢弃由 4 * 0 0 * * 0 0 表示的东西(在长度方面是固定的,但在内容方面不是固定的......意思可能是 3 * 1 0 * * 0 1 等等......) .

所以我的 file1 代表了我想要查找并保存在 file2 中的我的 ID 的一种“参考”。

我很难解释。我希望你明白我想做什么。

我认为 grep 应该可以工作,但我不知道如何 grep 仅在一行中提供一些信息并与另一个文件进行比较。

【问题讨论】:

    标签: bash sed awk grep line


    【解决方案1】:

    假设 file2 仅包含您想要的键 ID 列表:

    awk 'NR==FNR{ids[$0];next} $1 in ids{print $1,$10,$11}' file2 file1
    

    【讨论】:

      【解决方案2】:

      可以使用 for 循环

          outputfile="/tmp/something"
          file1=3; file2=4; 
          for ids in $(cat $file1|awk '{print $1}'); 
          do
                #echo working on $id**
                grep $ids $file2|awk '{print $3" "$4" "$5}' >> $outputfile
          done
      

      上面是现在扩展的相同脚本并将输出发送到文件,因此您可以执行脚本并让它处理放置输出的位置,而不是将脚本泵送到文件中。

      当然你可以在大文件上运行它,它可能需要一段时间才能开始,可能需要一些时间才能完成,使用这种方法的问题是它有效且易于使用,但可能不如建议使用其他一些复杂的方法。

      您可以启用正在工作的 id 行以获得更多详细信息

      补充说明:

      for filesfound in $(pattern=1101; grep $pattern 3*|awk -F":" '{print $1}'); do
       echo "found $filesfound"; 
       grep "newpattern" $filesfound; 
       done;
      
      found 3
      found 33
      

      您可以像这样进一步挖掘初始 grep:

       grep $pattern *|awk -F":" '{print "-- FILE: " $1 " --- ENTIRE_STRING: "$0}'
      -- FILE: 3 --- ENTIRE_STRING: 3:HWI-1KL104:145:C18ANACXX:5:1101:1168:2164   4   *   0   0   *   *   0   0   GTGCCTGAACTGGATGCATNGACAATGGGGAACATTACATATATAATACAAGGGAAACTCAAACGTTTCCNNNNNCAAGTATTTGACAGNNNNNNNNNNNN   @B@DDFFFHHHHHIHIJIJ#3AFGHHJJJJIIJJIJIIIJJJJJJJGIIJIJJJIJIJJJJIJJI=@EED#####,,5=;ADDFEEDDD############
      -- FILE: 33 --- ENTIRE_STRING: 33:HWI-1KL104:145:C18ANACXX:5:1101:1168:2164   4   *   0   0   *   *   0   0   GTGCCTGAACTGGATGCATNGACAATGGGGAACATTACATATATAATACAAGGGAAACTCAAACGTTTCCNNNNNCAAGTATTTGACAGNNNNNNNNNNNN   @B@DDFFFHHHHHIHIJIJ#3AFGHHJJJJIIJJIJIIIJJJJJJJGIIJIJJJIJIJJJJIJJI=@EED#####,,5=;ADDFEEDDD############
      

      现在返回文件名|所有字符串,然后查找模式并返回模式之后的所有内容 - 您可以通过在行尾添加更多 awk 语句来自定义它

      pattern=1101; grep $pattern *|awk -F":" '{print $1"|"$0}'|awk -F"$pattern" '{print $2}'
      :1168:2164   4   *   0   0   *   *   0   0   GTGCCTGAACTGGATGCATNGACAATGGGGAACATTACATATATAATACAAGGGAAACTCAAACGTTTCCNNNNNCAAGTATTTGACAGNNNNNNNNNNNN   @B@DDFFFHHHHHIHIJIJ#3AFGHHJJJJIIJJIJIIIJJJJJJJGIIJIJJJIJIJJJJIJJI=@EED#####,,5=;ADDFEEDDD############
      :1168:2164   4   *   0   0   *   *   0   0   GTGCCTGAACTGGATGCATNGACAATGGGGAACATTACATATATAATACAAGGGAAACTCAAACGTTTCCNNNNNCAAGTATTTGACAGNNNNNNNNNNNN   @B@DDFFFHHHHHIHIJIJ#3AFGHHJJJJIIJJIJIIIJJJJJJJGIIJIJJJIJIJJJJIJJI=@EED#####,,5=;ADDFEEDDD############
      

      【讨论】:

      • 完美!有用!非常感谢!!!但是我不明白如何将它打印到我在 '{print $3" "$4" "$5}' 之后放置 > results.txt 的文件中,但它没有用。我也试过 ./test.sh | tee results.txt 它有效,但它也打印了结果!
      • 已解决...对不起,它只是:./myscript.sh > results.txt 真让我感到羞耻 :) 只是一个问题...您认为它会在合理的时间内使用 file2 25GB? File1 我们只有 5Mb。
      • 没问题,我已经修改了原帖并对您的问题进行了更深入的了解。
      • 我的想法是通过更复杂的方法将大文件拆分为较小的文件并对它们执行 grep。您认为它可以加快分析速度吗?但是可以对多个文件执行 grep 吗?我试过:做 grep $ids file*| awk...但是它不起作用...
      • 模式=1101; grep $pattern 3*|awk -F":" '{print $1}' 是的,上面将打印出包含您的模式的每个文件,其中文件名是 3 或 33,或者如果您将 3* 更改为 * 那么它的所有文件..
      【解决方案3】:

      目前尚不清楚您想要 file2 的哪些字段,但一个好的起点应该是这样的:

      grep -Ff file1 file2 | tr -s ' ' | cut -d' ' -f1,9,10
      

      或者如果 file2 是制表符分隔的:

      grep -Ff file1 file2 | cut -f1,9,10
      

      顺便说一句,您可能应该将此数据保存在数据库中,而不是文本文件中。

      【讨论】:

      • 我认为 file2 是制表符分隔的。 9 和 10 代表什么?
      【解决方案4】:

      4 * 0 0 * * 0 0 总是采用相同的格式吗?在不了解各种可能情况的情况下,很难说如何回答这个问题。 id 呢,总是一样的格式吗?

      要使用 grep(而不是整行)仅获取 id,请使用 -o。这只会返回匹配的文本,而不是整行。

      要写入新文件并丢弃4 * 0 0 * * 0 0,您可以使用grep -v grep 字符串的倒数。所以如果你已经知道你正在使用哪条线路,grep -v '4 * 0 0 * * 0 0'

      无论如何,这在很大程度上取决于您输入的确切格式以及各种边缘情况,但这可能会让您入门。

      【讨论】:

      • yes 4 * 0 0 * * 0 0 始终采用相同的格式,但内容会发生变化。 ID也是相同的格式
      • Gotcha,那么使用一些正则表达式应该很容易用 grep 来查找您要查找的内容。
      猜你喜欢
      • 2012-01-01
      • 2018-12-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-09-23
      • 1970-01-01
      • 2018-03-04
      • 1970-01-01
      相关资源
      最近更新 更多