mar*_*ark 24 linux bash scripting perl command-line
在linux/shell环境中工作,我该如何完成以下任务:
文本文件1包含:
1
2
3
4
5
Run Code Online (Sandbox Code Playgroud)
文本文件2包含:
6
7
1
2
3
4
Run Code Online (Sandbox Code Playgroud)
我需要提取文件2中不在文件1中的条目.因此在本例中为'6'和'7'.
我如何从命令行执行此操作?
非常感谢!
Sie*_*geX 51
$ awk 'FNR==NR {a[$0]++; next} !a[$0]' file1 file2
6
7
Run Code Online (Sandbox Code Playgroud)
代码如何工作的说明:
细节说明:
FNR 是当前文件的记录号NR 是所有输入文件的当前总记录数FNR==NR 只有当我们读取file1时才是真的$0 是当前的文本行a[$0] 是一个哈希,键设置为当前文本行a[$0]++ 跟踪我们已经看到的当前文本行!a[$0] 只有当我们没有看到行文本时才是真的Dan*_*her 16
使用一些鲜为人知的实用程序:
sort file1 > file1.sorted
sort file2 > file2.sorted
comm -1 -3 file1.sorted file2.sorted
Run Code Online (Sandbox Code Playgroud)
这将输出重复项,因此如果有1 3in file1,但是2 in file2,这仍然会输出1 3.如果这不是你想要的,从输出管道sort通过uniq其写入文件之前:
sort file1 | uniq > file1.sorted
sort file2 | uniq > file2.sorted
comm -1 -3 file1.sorted file2.sorted
Run Code Online (Sandbox Code Playgroud)
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
Run Code Online (Sandbox Code Playgroud)
我的基准测试结果简而言之:
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
Run Code Online (Sandbox Code Playgroud)
最快运行的典型结果
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
Run Code Online (Sandbox Code Playgroud)
顺便说一句,对于awkies:它看起来a[$0]=1比速度更快a[$0]++,而且(!($0 in a))速度更快(!a[$0]).因此,对于awk解决方案,我建议:
awk 'FNR==NR{a[$0]=1;next}!($0 in a)' file1 file2
Run Code Online (Sandbox Code Playgroud)
怎么样:
diff file_1 file_2 | grep '^>' | cut -c 3-
Run Code Online (Sandbox Code Playgroud)
这将打印file_2中不在file_1中的条目.对于相反的结果,只需要用'<'替换'>'.'cut'删除'diff'添加的前两个字符,这些字符不是原始内容的一部分.
甚至不需要对文件进行排序.