提取两组/文件之间的唯一值
- 2024-11-07 08:55:00
- admin 原创
- 29
问题描述:
在 linux/shell 环境中工作,如何完成以下操作:
文本文件 1 包含:
1
2
3
4
5
文本文件 2 包含:
6
7
1
2
3
4
我需要提取文件 2 中不在文件 1 中的条目。所以在这个例子中是“6”和“7”。
我如何从命令行执行此操作?
非常感谢!
解决方案 1:
$ awk 'FNR==NR {a[$0]++; next} !($0 in a)' file1 file2
6
7
代码工作原理的解释:
如果我们正在处理文件 1,请跟踪我们看到的每一行文本。
如果我们正在处理文件 2,并且没有看到行文本,则打印它。
详细说明:
FNR
是当前文件的记录号NR
是所有输入文件的当前总记录数FNR==NR
仅当我们读取 file1 时才为真$0
是当前文本行a[$0]
是一个哈希表,其键设置为当前文本行a[$0]++
跟踪我们看到的当前文本行!($0 in a)
仅当我们没有看到行文本时才为真如果上述模式返回 true,则打印文本行,这是未给出明确操作时的默认 awk 行为
解决方案 2:
使用一些鲜为人知的实用程序:
sort file1 > file1.sorted
sort file2 > file2.sorted
comm -1 -3 file1.sorted file2.sorted
3
这将输出重复项,因此如果中有 1 file1
,但 中有 2 file2
,则仍将输出 1 3
。 如果这不是您想要的,请在将输出写入文件之前将其通过sort
管道传输:uniq
sort file1 | uniq > file1.sorted
sort file2 | uniq > file2.sorted
comm -1 -3 file1.sorted file2.sorted
GNU coreutils 包中有很多实用程序,允许进行各种文本操作。
解决方案 3:
我想知道以下哪种解决方案对于“较大”的文件来说是“最快”的:
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
。如果 file1 和 file2 已经排序,
comm
则join
比 awk1 + awk2 快得多。(当然,它们不假设文件已排序。)awk1 + awk2 据称使用更多 RAM 和更少 CPU。实际运行时间较短,
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
顺便说一句,对于 awkies 来说:似乎a[$0]=1
比 快a[$0]++
,并且(!($0 in a))
比 快(!a[$0])
。因此,对于 awk 解决方案,我建议:
awk 'FNR==NR{a[$0]=1;next}!($0 in a)' file1 file2
解决方案 4:
怎么样:
diff file_1 file_2 | grep '^>' | cut -c 3-
这将打印 file_2 中不存在于 file_1 中的条目。要获得相反的结果,只需将 '>' 替换为 '<'。'cut' 会删除由 'diff' 添加的前两个字符,这两个字符不是原始内容的一部分。
文件甚至不需要排序。
解决方案 5:
使用 grep:
grep -F -x -v -f file_1 file_2
解决方案 6:
这是另一个 awk 解决方案
$ awk 'FNR==NR{a[$0]++;next}(!($0 in a))' file1 file2
6
7
解决方案 7:
$ cat file1 file1 file2 | sort | uniq -u
6
7
uniq——报告或过滤文件中的重复行
... 如果输入中的重复行不相邻,则不会检测到,因此可能需要先对文件进行排序。
-u Only output lines that are not repeated in the input.
打印 file1 两次以确保跳过 file1 中的所有条目uniq -u
。
解决方案 8:
cat file1 file2 | sort -u > unique
解决方案 9:
如果您确实想从命令行执行此操作,此站点(搜索“未找到重复项”)有一个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),但它可以完成工作。
- 2024年20款好用的项目管理软件推荐,项目管理提效的20个工具和技巧
- 2024年开源项目管理软件有哪些?推荐5款好用的项目管理工具
- 项目管理软件有哪些?推荐7款超好用的项目管理工具
- 项目管理软件哪个最好用?盘点推荐5款好用的项目管理工具
- 项目管理软件有哪些最好用?推荐6款好用的项目管理工具
- 项目管理软件有哪些,盘点推荐国内外超好用的7款项目管理工具
- 2024项目管理软件排行榜(10类常用的项目管理工具全推荐)
- 项目管理软件排行榜:2024年项目经理必备5款开源项目管理软件汇总
- 2024年常用的项目管理软件有哪些?推荐这10款国内外好用的项目管理工具
- 项目管理必备:盘点2024年13款好用的项目管理软件