代码之家  ›  专栏  ›  技术社区  ›  too much php

查找两个文件中公用行的Unix命令

  •  153
  • too much php  · 技术社区  · 16 年前

    我确信我曾经找到一个Unix命令,它可以从两个或多个文件中打印公共行,有人知道它的名字吗?它比 diff .

    11 回复  |  直到 7 年前
        1
  •  183
  •   Mohammed H    7 年前

    你要寻求的命令是 comm . 例如:

    comm -12 1.sorted.txt 2.sorted.txt
    

    在这里:

    - 1 :取消显示列1(1.sorted.txt特有的行)

    - 2 :取消显示第2列(2.sorted.txt特有的行)

        2
  •  54
  •   Jonathan Leffler    9 年前

    轻松应用 康姆 命令到 未分类的 文件,使用bash的 process substitution :

    $ bash --version
    GNU bash, version 3.2.51(1)-release
    Copyright (C) 2007 Free Software Foundation, Inc.
    $ cat > abc
    123
    567
    132
    $ cat > def
    132
    777
    321
    

    因此,abc和def文件有一个共同的行,即带有“132”的行。 使用 康姆 在未排序的文件上:

    $ comm abc def
    123
        132
    567
    132
        777
        321
    $ comm -12 abc def # No output! The common line is not found
    $
    

    最后一行没有输出,公共行没有被发现。

    现在使用 康姆 对于已排序的文件,使用进程替换对文件进行排序:

    $ comm <( sort abc ) <( sort def )
    123
                132
        321
    567
        777
    $ comm -12 <( sort abc ) <( sort def )
    132
    

    现在我们有132线了!

        3
  •  24
  •   Johannes Schaub - litb    16 年前

    也许你的意思是 comm ?

    逐行比较排序文件file1和file2。

    如果没有选项,则生成三列输出。第一列 包含文件1、列的唯一行 两个包含唯一的行 文件2和列3包含两个文件共用的行。

    找到这些信息的秘密是信息页面。对于GNU程序,它们比它们的手册页更详细。尝试 info coreutils 它会列出所有有用的小实用程序。

        4
  •  23
  •   Jonathan Leffler    9 年前

    为了补充perl-One的内衬,这里是它的 awk 当量:

    awk 'NR==FNR{arr[$0];next} $0 in arr' file1 file2
    

    这将读取 file1 进入数组 arr[] ,然后检查每一行 file2 如果它已经存在于数组中(即 文件1 )找到的行将按它们出现的顺序打印。 文件2 . 注意比较 in arr 使用来自的整行 文件2 作为数组的索引,因此它只报告整行的精确匹配。

        5
  •  18
  •   ferdy    10 年前

    同时

    grep -v -f 1.txt 2.txt > 3.txt
    

    给出了两个文件(2.txt和1.txt中的文件)的区别,您可以轻松地执行

    grep -f 1.txt 2.txt > 3.txt
    

    收集所有公共行,这应该为您的问题提供一个简单的解决方案。如果你有已排序的文件,你应该 comm 尽管如此。当做!

        6
  •  8
  •   Sam I am says Reinstate Monica    11 年前
    perl -ne 'print if ($seen{$_} .= @ARGV) =~ /10$/'  file1 file2
    
        7
  •  5
  •   R S John    8 年前
    awk 'NR==FNR{a[$1]++;next} a[$1] ' file1 file2
    
        8
  •  4
  •   Basj    7 年前

    如果这两个文件尚未排序,则可以使用:

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

    它会工作,避免错误信息 comm: file 2 is not in sorted order 什么时候做 comm -12 a.txt b.txt .

        9
  •  3
  •   Master DJon    9 年前

    在Linux的有限版本上(比如我正在研究的qnap(nas)):
    -通信不存在
    - grep -f file1 file2 可能会导致一些问题,如@christopherschultz和使用 grep -F -f file1 file2 速度真的很慢(超过5分钟-还没完成-超过2-3秒,用下面的方法处理超过20MB的文件)

    我是这样做的:

    sort file1 > file1.sorted
    sort file2 > file2.sorted
    
    diff file1.sorted file2.sorted | grep "<" | sed 's/^< *//' > files.diff
    diff file1.sorted files.diff | grep "<" | sed 's/^< *//' > files.same.sorted

    如果“files.same.sorted”的顺序应与原始的顺序相同,则应按与file1相同的顺序添加此行:

    awk 'FNR==NR {a[$0]=$0; next}; $0 in a {print a[$0]}' files.same.sorted file1 > files.same

    或者,对于与文件2相同的顺序:

    awk 'FNR==NR {a[$0]=$0; next}; $0 in a {print a[$0]}' files.same.sorted file2 > files.same

        10
  •  2
  •   Jonathan Leffler    7 年前

    仅供参考如果有人仍在寻找如何对多个文件执行此操作,请参见链接的答案 Finding matching lines across many files.


    结合这两个答案( ans1 ans2 ,我认为您可以在不排序文件的情况下获得所需的结果:

    #!/bin/bash
    ans="matching_lines"
    
    for file1 in *
    do 
        for file2 in *
            do 
                if  [ "$file1" != "$ans" ] && [ "$file2" != "$ans" ] && [ "$file1" != "$file2" ] ; then
                    echo "Comparing: $file1 $file2 ..." >> $ans
                    perl -ne 'print if ($seen{$_} .= @ARGV) =~ /10$/' $file1 $file2 >> $ans
                fi
             done 
    done
    

    只需保存它,赋予它执行权( chmod +x compareFiles.sh 然后运行它。它将获取当前工作目录中存在的所有文件,并对结果进行“匹配行”文件中的所有与所有的比较。

    有待改进的方面:

    • 跳过目录
    • 避免将所有文件进行两次比较(file1与file2和file2与file1)。
    • 可能在匹配字符串旁边添加行号
        11
  •  -2
  •   Jonathan Leffler    9 年前
    rm file3.txt
    
    cat file1.out | while read line1
    do
            cat file2.out | while read line2
            do
                    if [[ $line1 == $line2 ]]; then
                            echo $line1 >>file3.out
                    fi
            done
    done
    

    应该这样做。