我确信我曾经发现过一个shell命令,它可以从两个或多个文件中打印公共行。它叫什么名字?

它比diff简单多了。


当前回答

awk 'NR==FNR{a[$1]++;next} a[$1] ' file1 file2

其他回答

要轻松地将comm命令应用到未排序的文件,请使用Bash的进程替换:

$ 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:

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

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

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

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

现在我们到了132线!

这不是你想问的,但我认为这对于描述一个稍微不同的场景还是有用的

如果你只是想快速确定一堆文件之间是否有重复的行,你可以使用这个快速解决方案:

cat a_bunch_of_files* | sort | uniq | wc

如果你得到的行数比你得到的少

cat a_bunch_of_files* | wc

然后是一些重复的线条。

有关如何为多个文件执行此操作,请参阅跨多个文件查找匹配行的链接答案。


结合这两个答案(答案1和答案2),我认为你可以得到你需要的结果,而不需要对文件进行排序:

#!/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)并运行它。它将获取当前工作目录中的所有文件,并进行all-vs-all比较,将结果留在“matching_lines”文件中。

需要改进的地方:

跳过目录 避免将所有文件进行两次比较(file1 vs file2和file2 vs file1)。 可以在匹配的字符串旁边添加行号

perl -ne 'print if ($seen{$_} .= @ARGV) =~ /10$/'  file1 file2
awk 'NR==FNR{a[$1]++;next} a[$1] ' file1 file2