在linux / shell环境下工作,我该如何完成以下工作:
文本文件1包含:
1 2 3 4 5
文本文件2包含:
6 7 1 2 3 4
我需要提取文件2中不在文件1中的条目。因此,在本例中为“6”和“7”。
我如何从命令行执行此操作?
非常感谢!
$ awk 'FNR==NR {a[$0]++; next} !a[$0]' file1 file2 6 7
代码如何工作的说明:
详细说明:
FNR
是当前文件的记录号码 NR
是来自所有输入文件的当前整体记录编号 FNR==NR
只有当我们正在读取file1时才是真的 $0
是文本的当前行 a[$0]
是一个散列,其中的键设置为当前文本行 a[$0]++
跟踪我们已经看到的当前文本行 !a[$0]
只有当我们没有看到行文字时, !a[$0]
才是真的 使用一些鲜为人知的实用工具:
sort file1 > file1.sorted sort file2 > file2.sorted comm -1 -3 file1.sorted file2.sorted
这将输出重复的内容,所以如果file1
有1 3
,但是file2
2个,这仍然会输出1 3
。 如果这不是你想要的,那么在将它写入文件之前,通过uniq
管道输出sort
:
sort file1 | uniq > file1.sorted sort file2 | uniq > file2.sorted comm -1 -3 file1.sorted file2.sorted
GNU coreutils软件包中有很多实用程序,允许进行各种文本操作。
我想知道以下哪个解决方案对于“更大”的文件是“最快”的:
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
比comm
稍快。 comm
和join
比awk1 + awk2快得多。 (当然,他们不承担排序的文件。) 为了简洁起见,我省略了全部细节。 不过,我想任何有兴趣的人都可以联系我或者重复测试。 粗略地说,设置是
# 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
顺便说一句,对于awkies:似乎a[$0]=1
比a[$0]++
快,并且(!($0 in a))
比(!a[$0])
更快。 所以,对于awk解决方案,我建议:
awk 'FNR==NR{a[$0]=1;next}!($0 in a)' file1 file2
用grep:
grep -F -x -v -f file_1 file_2
怎么样:
diff file_1 file_2 | grep '^>' | cut -c 3-
这将打印file_2中不在file_1中的条目。 对于相反的结果,只需用'<'替换'>'即可。 'cut'删除由'diff'添加的前两个字符,这些字符不是原始内容的一部分。
这些文件甚至不需要排序。
这里是另一个awk解决方案
$ awk 'FNR==NR{a[$0]++;next}(!($0 in a))' file1 file2 6 7
如果你真的从命令行设置这个, 这个网站 (搜索“找不到重复”)有一个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)的时间复杂度,但它可以完成这项工作。