您好,我有两个文件,它们的文件名如下所示:
文件 1:
123.txt
456.txt
789.txt
101112.txt
文件 2:
123.txt
789.txt
101112.txt
是否有任何 bash 命令可用于重叠它们并仅打印不匹配的行或文件名。所以我期望类似这样的结果:
456.txt
答案1
comm
你的朋友在这里吗:
如果文件已经排序:
comm -3 f1.txt f2.txt
如果未排序,sort
则使用进程替换将它们作为文件描述符传递(这样我们就不需要任何临时文件):
comm -3 <(sort f1.txt) <(sort f2.txt)
例子:
% cat f1.txt
123.txt
456.txt
789.txt
101112.txt
% cat f2.txt
123.txt
789.txt
101112.txt
% comm -3 <(sort f1.txt) <(sort f2.txt)
456.txt
答案2
一种简单的方法是使用两个“grep”命令,每个命令将其中一个文件作为行列表来搜索另一个文件。假设您的文件名为 f1.txt 和 f2.txt:
grep -Fxvf f1.txt f2.txt ; grep -xvf f2.txt f1.txt
使用的选项grep
如下:
-F
- 使用每一行作为固定字符串进行匹配,而不是正则表达式-x
- 仅匹配整行-v
- 反转匹配以选择不匹配的行-f
- 使用作为参数给出的文件作为要匹配的模式列表
答案3
我理解你的问题是,你想要所有行只出现在其中一个文件中,而不是两个文件中,并且忽略行顺序。
我还假设我们比较文件f1.txt
和f2.txt
。插入你们各自的名字。
使用 Bash,你可以用两个循环来实现,每个循环处理一个文件并检查每一行是否出现在另一个文件中。这种方法效率不高,但应该可以工作:
# This loops over f1.txt and searches each line in f2.txt
while read line ; do grep -Fxqe "$line" f2.txt || echo "$line" ; done < f1.txt
# This loops over f2.txt and searches each line in f1.txt
while read line ; do grep -Fxqe "$line" f1.txt || echo "$line" ; done < f2.txt
两个循环一起产生所需的结果。每个循环本身仅检查一个文件中没有出现在另一个文件中的行。
可以使用例如简短的 Python 单行代码来编写更简洁的解决方案:
python3 -c 's1=set(open("f1.txt")); s2=set(open("f2.txt")); print(*s1.symmetric_difference(s2), sep="")'
这使用了一个集合数据结构,它只包含唯一值并允许像“对称差异”这样的集合操作。
请注意,使用这两种解决方案时,如果任何文件包含重复的行,这些行将被忽略并仅作为单个事件处理。
答案4
假设您不需要结果保持原始顺序,只需使用:
cat file1 file2 | sort | uniq -u
解释:
cat file1 file2
将两个文件依次输出到标准输出。
sort
对两个文件的组合内容进行排序。我们感兴趣的有用的副作用是,这会将两个文件中相同的行放在一起。
uniq -u
仅输出“唯一”的行,即仅出现一次的行。令人讨厌的是,它只查看相邻的行对,这就是为什么前一个sort
命令是必要的。
您还可以使用uniq -d
仅输出出现两次的行。这将为您提供两个文件共有的行。
笔记:如果相同的行在同一个文件中出现多次,我不确定这个解决方案的效果如何。