如何在bash中找到多个文件的“完全对称差异”?

时间:2019-07-08 13:37:01

标签: bash text-processing

我有五个文件,每个文件都列出了完整的文件路径,如下所示:

File one
    /full/file/path/one.xlsx
    /full/file/path/two.txt
    /full/file/path/three.pdf
    ....
File two
    /a/b/c/d/r.txt
    /full/file/path/two.txt
    ....
File three
    /obe/two/three/graph.m
    /full/file/path/two.txt
    ....
File four
    .....
File five
     .....

所有五个文件可能都包含相同的完全文件路径。但是,我想过滤出每个文件共有的路径。换句话说,我希望删除所有文件的总交集。以下是一个视觉辅助工具,它以三个文件的较小示例描述了我想要的内容(对不起,我的鼠标绘图能力很差):

enter image description here

symmetric difference上的页面没有准确描述我想要的内容,因此视觉辅助和短语完全对称差异周围的引号。

问题

如何过滤几个文件中的文本行以获得上面想要的情况?

1 个答案:

答案 0 :(得分:2)

假设每个文件都没有重复项,

  • 合并所有文件(cat file1 file2 ... file5
  • 计算每行出现的频率(sort | uniq -c
  • 仅保留少于五次的行(sed -En 's/^ *[1-4] //p'

sort file1 ... file5 | uniq -c | sed -En 's/^ *[1-4] //p'

但是,如果某些文件可能包含同一行多次,而不是您必须先删除这些重复项,那么

f() { sort -u "$1"; }
sort <(f file1) ... <(f file5) | uniq -c | sed -En 's/^ *[1-4] //p'

或(速度较慢,但​​易于编辑)

for i in file1 ... file5; do sort -u "$i"; done |
sort | uniq -c | sed -En 's/^ *[1-4] //p'

如果出于某种原因要保留单个文件中的重复项,并且还希望保留行的原始顺序,则可以将以上命令反转为仅打印出现在每个文件中的行,并使用{{1 }}:

grep

或(速度较慢,但​​易于编辑)

f() { sort -u "$1"; }
grep -Fxvhf <(sort <(f file1) ... <(f file5) |
              uniq -c | sed -En 's/^ *5 //p') file1 ... file5