【问题标题】:Check if all lines of a file are contained in another file检查文件的所有行是否包含在另一个文件中
【发布时间】:2014-12-10 08:53:26
【问题描述】:

我有一个文件:a.txt,每行都有一个数字。我还有另一个文件b.txt,每行都有一个数字。
如何检查文件a.txt 中的所有行是否包含在b.txt 中?

【问题讨论】:

标签: linux bash file


【解决方案1】:

您可以为此使用comm

如果a.txtb.txt 已经排序(词法和升序),你只需要

comm -23 a.txt b.txt

或许

comm -23 a.txt b.txt | wc -l

如果没有输出(或者如果wc -l 返回“0”),那么a.txt 中的每一行都在b.txt 中(-2 抑制仅在b.txt、@987654331 中的行的输出@ 禁止输出两个文件中的行)。

如果文件未排序,您可以使用进程替换将每个文件的排序输出传递给comm

comm -23 <(sort a.txt) <(sort b.txt)

进程替换 &lt;(COMMAND)COMMAND 的输出放入 FIFO 或 /dev/fd 中的文件(取决于系统支持的内容)。然后在命令行上将&lt;(COMMAND) 替换为此文件的名称作为命令行扩展的一部分。

这确实会检查行,所以如果一个数字在a.txt 中存在两次,但在b.txt 中只存在一次,这将输出来自a.txt 的重复行。如果您不关心重复,请使用sort -u FILE 而不是sort FILE(或sort FILE | uniq,以防您的sort 没有唯一排序开关)

【讨论】:

    【解决方案2】:

    您可以使用diff 命令比较两个文件

    使用示例

    $ seq 1 5 > a.txt
    $ seq 1 5 > b.txt
    $ diff a.txt b.txt
    $
    $ seq 1 6 > b.txt
    $ diff a.txt b.txt
    5a6
    > 6
    

    编辑

    你也可以试试

    $ seq 1 5 > a.txt
    $ seq 1 5 > b.txt
    $ diff a.txt b.txt > /dev/null  && echo files are same || echo files are not same
    files are same
    $ seq 1 6 > b.txt
    $ diff a.txt b.txt > /dev/null  && echo files are same || echo files are not same
    files are not same
    

    【讨论】:

    • 但是,这两个文件中的数字顺序必须相同,对吧?
    • @mrtubis 是的,它需要。因为它将行与两个文件的相应行进行比较。您可以对这两个文件进行排序以确保安全
    • @nu11p01n73R:是的,适用于小文件。但是文件有 2K 行我怎么能从差异中理解它是一个子集?
    • @Jim 如果两个文件相同,则差异不会给出任何输出。好像有一些差异,它显示了
    • @Jim 我已经编辑了我对echo 的回答,如果有什么不同的话。希望对你有帮助
    【解决方案3】:

    如果数字是唯一的(每个文件中没有重复),您可以将它们连接起来,并通过管道进行排序,然后 uniq 并检查您有多少行。

    例如:

    >> cat a.txt
    1
    2
    8
    5
    >> cat b.txt
    1
    2
    5
    3
    8
    >> cat a.txt b.txt | sort | uniq | wc -l
    5
    

    由于答案与b.txt中的行数相同,所以答案是肯定的!

    【讨论】:

      【解决方案4】:

      试试这个:

      awk '
          NR==FNR{arr[$0]++;next}
          {print ($0 in arr) ? $0 " in both files" : $0 " *not* in both files"}
      ' b.txt a.txt
      

       $ diff -a b.txt a.txt
      2c2
      < 3
      ---
      > 2
      6d5
      < 7
      

      【讨论】:

        【解决方案5】:
        awk 'FNR==NR{b[$0];next}
                    {if($0 in b){print $0" is present in b.txt"}
                     else{print $0" is not present in b.txt"}
                    }' b.txt a.txt
        

        【讨论】:

        • 如果有多个相同的数字,这可能会产生误导性的结果。
        【解决方案6】:

        Perl 解决方案:

        #!/usr/bin/perl
        use strict;
        use warnings;
        use List::Compare;
        #read file a.txt
        open (my $fh, "<", "a.txt") or die $!;
        while (<$fh>){
            push @atxt = $_;
        }
        close($fh); 
        #read file b.txt
        open (my $fh2, "<", "b.txt") or die $!;
        while (<$fh2>){
            push @btxt = $_;
        } 
        close($fh2);
        
        my $lc = List::Compare->new(\@atxt, \@btxt);
        
        print $lc->get_intersection;
        print $lc->get_union;
        print $lc->get_unique;
        print $lc->get_complement;
        

        还有更多选项,请查看文档:http://search.cpan.org/~jkeenan/List-Compare-0.39/lib/List/Compare.pm

        【讨论】:

          【解决方案7】:

          包含另一个文件的文件意味着 a.txt 的全部内容以相同的顺序出现在 b.txt 中,包括可能的重复,而您的最后一个问题:

          如何检查文件 a.txt 中的所有行是否包含在 b.txt 中?

          暗示顺序和重复是不相关的。举个简单的例子:

          a.txt:
          
          5
          7
          3
          
          b.txt:
          
          9
          5
          3
          7
          

          满足您引用的问题,但不是标题中的问题。

          鉴于容器文件不是很大,解决引用的问题要容易得多(否则你会遇到内存问题,使用我将在下面演示的直接方法)。一个简单的解决方案是创建一组包含在 b.txt 中的所有数字,然后遍历 a.txt 并返回 false,以防在构造的集合中找不到项目。如果在您完成对 a.txt 内容的迭代时还没有发生这种情况,则返回 true。

          这在伪代码中如下所示:

          ContentSet = {}
          for each element b of b.txt
              add b into ContentSet
          
          for each element a of a.txt
              if a is not in ContentSet then return false
          
          return true
          

          这种方法的优点是第一次迭代消除了容器文件中可能的重复,因此将文件大小和搜索时间保持在最低限度,并且比给定的幼稚方法运行第二次迭代更快该集合具有良好的哈希实现,因为检查哈希集是否包含给定对象是一个 O(1) 操作。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2011-12-08
            • 1970-01-01
            • 2012-06-03
            • 2014-01-20
            • 2021-08-31
            • 2020-01-13
            • 1970-01-01
            相关资源
            最近更新 更多