我确定我曾经发现一个unix命令可以打印两个或多个文件中的公共行,有人知道它的名字吗?它比diff
简单得多。
答案 0 :(得分:189)
您正在寻找的命令是comm
。例如: -
comm -12 1.sorted.txt 2.sorted.txt
下面:
-1 :取消第1列(1.sorted.txt独有的行)
-2 :取消第2列(2.sorted.txt独有的行)
答案 1 :(得分:55)
要轻松将 comm 命令应用于未排序文件,请使用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 :
$ 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行!
答案 2 :(得分:24)
也许你的意思是comm
?
逐行比较已排序的文件FILE1和FILE2。
没有选项,产生三列输出。第一栏 包含FILE1列唯一的行 两个包含唯一的行 FILE2和第三列包含两个文件共有的行。
查找这些信息的秘诀是信息页面。对于GNU程序,它们比人工页面更详细。试试info coreutils
,它会列出所有小的有用工具。
答案 3 :(得分:24)
为了补充Perl单行,这里是它的awk
等价物:
awk 'NR==FNR{arr[$0];next} $0 in arr' file1 file2
这将读取file1
到数组arr[]
的所有行,然后检查file2
中的每一行是否已存在于数组中(即file1
) 。找到的行将按照它们在file2
中的显示顺序打印。
请注意,比较in arr
使用file2
中的整行作为数组的索引,因此它只会在整行上报告完全匹配。
答案 4 :(得分:18)
虽然
grep -v -f 1.txt 2.txt > 3.txt
为您提供两个文件的区别(2.txt中的内容,而不是1.txt中的内容),您可以轻松地执行此操作
grep -f 1.txt 2.txt > 3.txt
收集所有常用行,这应该可以为您的问题提供简单的解决方案。如果您已对文件进行了排序,则应该comm
。此致!
答案 5 :(得分:8)
perl -ne 'print if ($seen{$_} .= @ARGV) =~ /10$/' file1 file2
答案 6 :(得分:5)
awk 'NR==FNR{a[$1]++;next} a[$1] ' file1 file2
答案 7 :(得分:4)
如果这两个文件尚未排序,您可以使用:
comm -12 <(sort a.txt) <(sort b.txt)
并且它会起作用,在执行comm: file 2 is not in sorted order
时避免出现错误消息comm -12 a.txt b.txt
。
答案 8 :(得分:3)
在限量版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
或者,与file2相同的顺序:
awk 'FNR==NR {a[$0]=$0; next}; $0 in a {print a[$0]}' files.same.sorted file2 > files.same
答案 9 :(得分:2)
仅供参考,如果有人仍在查看如何为多个文件执行此操作,请参阅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
)并运行它。它将获取当前工作目录中存在的所有文件,并将在“matching_lines”文件中进行全对比比较结果。
有待改进的地方:
答案 10 :(得分:-2)
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
这应该这样做。