17

如何在 Bash 中从另一个集合中减去一个集合?

这类似于:bash 中是否存在“集合”数据结构?但不同的是它询问如何使用代码执行减法

  • set1:N行作为过滤器的输出
  • set2:M 行作为过滤器的输出

怎么获得:

  • set3:N中所有未出现在M中的行
4

5 回答 5

15
comm -23 <(command_which_generate_N|sort) <(command_which_generate_M|sort)

不带选项的 comm 显示 3 列输出:1:仅在第一个文件中,2:仅在第二个文件中,3:在两个文件中。-23 删除第二列和第三列。

$ cat > file1.list
A
B
C
$ cat > file2.list
A
C
D
$ comm file1.list file2.list 
        A
B
        C
    D
$ comm -12 file1.list file2.list # In both
A
C
$ comm -23 file1.list file2.list # Only in set 1
B
$ comm -13 file1.list file2.list # Only in set 2
D

输入文件必须排序。

GNU sort 和 comm 取决于语言环境,例如输出顺序可能不同(但内容必须相同)

(export LC_ALL=C; comm -23 <(command_which_generate_N|sort) <(command_which_generate_M|sort))
于 2012-08-15T05:21:28.677 回答
4

uniq -u(manpage)通常是最简单的列表减法工具:

用法

uniq [OPTION]... [INPUT [OUTPUT]] 
[...]
-u, --unique
    only print unique lines

示例:列出在目录 a 中找到但不在 b 中的文件

$ ls a
file1  file2  file3
$ ls b
file1  file3

$ echo "$(ls a ; ls b)" | sort | uniq -u
file2
于 2017-05-18T09:16:11.520 回答
1

我最近编写了一个名为 Setdown 的程序,它从 cli 执行 Set 操作(如设置差异)。

它可以通过编写类似于您在 Makefile 中编写的定义来执行集合操作:

someUnion: "file-1.txt" \/ "file-2.txt"
someIntersection: "file-1.txt" /\ "file-2.txt"
someDifference: someUnion - someIntersection

它很酷,你应该检查一下。我个人不推荐“在 unix shell 中设置操作”的帖子。当您确实需要执行许多集合操作或者您有任何相互依赖的集合操作时,它不会很好地工作。

无论如何,我认为这很酷,您应该完全检查一下。

于 2015-01-30T02:35:52.587 回答
1

我有一个非常简单的 1-liner:

$ now=(ConfigQC DBScripts DRE DataUpload WFAdaptors.log)

$ later=(ConfigQC DBScripts DRE DataUpload WFAdaptors.log baz foo)

$ printf "%s\n" $now $later | sort | uniq -c | grep -vE '[ ]+2.*' | awk '{print $2}'
baz
foo

根据定义,如果两个集合具有共同的元素,则它们相交。在这种情况下,有 2 个集合,所以任何 2 的计数都是一个交集 - 只需用 grep “减去”它们

于 2020-04-19T09:15:27.173 回答
0

您可以使用差异

# you should sort the output
ls > t1
cp t1 t2

我用 vi 从 t2 中删除了一些条目

$ cat t1
AEDWIP.writeMappings.sam
createTmpFile.sh*
find.out
grepMappingRate.sh*
salmonUnmapped.sh*
selectUnmappedReadsFromFastq.sh*

$ cat t2
AEDWIP.writeMappings.sam
createTmpFile.sh*
salmonUnmapped.sh*
selectUnmappedReadsFromFastq.sh*

diff 报告 t1 中不在 t2 中的行

diff t1 t2
$ diff t1 t2
3,4d2
< find.out
< grepMappingRate.sh*

拼装版

diff t1 t2 | grep "^<" | cut -d " " -f 2
find.out
grepMappingRate.sh*
于 2021-05-06T02:28:18.433 回答