在linux / shell环境中工作,我该如何完成以下任务:
文本文件1包含:
1
2
3
4
5
文本文件2包含:
6
7
1
2
3
4
我需要提取文件2中不在文件1中的条目。因此本例中为“6”和“7”。
如何从命令行执行此操作?
非常感谢!答案 0 :(得分:45)
$ awk 'FNR==NR {a[$0]++; next} !a[$0]' file1 file2
6
7
代码如何工作的说明:
细节说明:
FNR
是当前文件的记录编号NR
是所有输入文件的当前总记录数FNR==NR
仅在我们阅读file1 $0
是当前的文字行a[$0]
是一个哈希,其键设置为当前文本行a[$0]++
跟踪我们看到的当前文字行!a[$0]
才属实
答案 1 :(得分:14)
使用一些鲜为人知的实用程序:
sort file1 > file1.sorted
sort file2 > file2.sorted
comm -1 -3 file1.sorted file2.sorted
这将输出重复项,因此如果3
中有file1
,file2
中有2 {},则仍会输出1 3
。如果这不是您想要的,请将输出从sort
传递到uniq
,然后再将其写入文件:
sort file1 | uniq > file1.sorted
sort file2 | uniq > file2.sorted
comm -1 -3 file1.sorted file2.sorted
GNU coreutils包中有许多实用程序,允许进行各种文本操作。
答案 2 :(得分:8)
我想知道以下哪种解决方案对于“更大”的文件来说是“最快的”:
awk 'FNR==NR{a[$0]++}FNR!=NR && !a[$0]{print}' file1 file2 # awk1 by SiegeX
awk 'FNR==NR{a[$0]++;next}!($0 in a)' file1 file2 # awk2 by ghostdog74
comm -13 <(sort file1) <(sort file2)
join -v 2 <(sort file1) <(sort file2)
grep -v -F -x -f file1 file2
简言之我的基准测试结果:
grep -Fxf
,它要慢得多(在我的测试中是2-4倍)。comm
略快于join
。comm
和join
比awk1 + awk2快得多。 (当然,他们不会假设已排序的文件。)comm
的实际运行时间较低,可能是因为它使用了更多的线程。 awk1 + awk2的CPU时间较短。为了简洁起见,我省略了全部细节。但是,我认为有兴趣的人可以联系我或者只是重复测试。粗略地说,设置是
# Debian Squeeze, Bash 4.1.5, LC_ALL=C, slow 4 core CPU
$ wc file1 file2
321599 321599 8098710 file1
321603 321603 8098794 file2
最快运行的典型结果
awk2: real 0m1.145s user 0m1.088s sys 0m0.056s user+sys 1.144
awk1: real 0m1.369s user 0m1.324s sys 0m0.044s user+sys 1.368
comm: real 0m0.980s user 0m1.608s sys 0m0.184s user+sys 1.792
join: real 0m1.080s user 0m1.756s sys 0m0.140s user+sys 1.896
grep: real 0m4.005s user 0m3.844s sys 0m0.160s user+sys 4.004
BTW,对于awkies:似乎a[$0]=1
比a[$0]++
快,而(!($0 in a))
比(!a[$0])
快。因此,对于awk解决方案,我建议:
awk 'FNR==NR{a[$0]=1;next}!($0 in a)' file1 file2
答案 3 :(得分:5)
使用grep:
grep -F -x -v -f file_1 file_2
答案 4 :(得分:5)
怎么样:
diff file_1 file_2 | grep '^>' | cut -c 3-
这将打印file_2中不在file_1中的条目。对于相反的结果,只需要替换&#39;&gt;&#39;用&#39;&lt;&#39; &#39;切&#39;删除由&#39; diff&#39;添加的前两个字符,这些字符不属于原始内容。
这些文件甚至不需要排序。
答案 5 :(得分:2)
这是另一个awk解决方案
$ awk 'FNR==NR{a[$0]++;next}(!($0 in a))' file1 file2
6
7
答案 6 :(得分:1)
cat file1 file2 | sort -u > unique
答案 7 :(得分:0)
如果你确实设置了从命令行执行此操作,this site(搜索“找不到重复项”)有一个awk
示例搜索重复项。这可能是一个很好的起点。
但是,我建议您使用Perl或Python。基本上,该计划的流程将是:
findUniqueValues(file1, file2){
contents1 = array of values from file1
contents2 = array of values from file2
foreach(value2 in contents2){
found=false
foreach(value1 in contents1){
if (value2 == value1) found=true
}
if(!found) print value2
}
}
这不是最优雅的方式,因为它具有O(n ^ 2)时间复杂度,但它可以完成这项工作。