我在 stackoverflow 社区上找到了类似的其他链接,但它们没有准确回答我的问题。
我有 2 个文件,行数不同,但我都对它们进行了排序。我的原始文件有数百行长,但出于故障排除目的,我将 file1 设置为 12 行,file2 设置为 5 行。文件 2 是文件 1 的子集。我想要做的是运行一个命令,输出 file1 中但不在 file2 中的所有行。
我尝试使用 Unix 命令diff
,comm
但它们都列出了 file1 的完整内容,这不是我想要的。
一个简单的例子是:
File1 File2
A B
B E
C I
E N
G O
I
L
M
N
O
X
所以在这里,我们可以看到 file2 中的所有内容都在 file1 中。由于某种原因,diff
两者comm
都显示了 file1 的完整内容。我认为这是因为它正在进行逐行比较而不是搜索整个文件。
我可以运行另一个 Unix 命令来输出我所期望的结果吗?
编辑:我用来尝试获取所需内容的命令是:
a) 比较文件1 文件2
这基本上列出了 file1 中的所有内容,前面有一个 < 显示内容来自 file1,前面有一个 > 列出了 file2 中的所有内容。绝对不是我需要的
b) 通讯 -23 文件1 文件2
这再次显示了 file1 的全部内容,而不是像我预期的那样的差异。我也
c) 通讯 -3 文件1 文件2
comm 的帮助页面说这将打印文件 1 中的行,但不会打印文件 2 中的行,反之亦然,但这也没有显示我在示例中想要的 b/c,B 出现在两个文件中但在不同的行上。然而,输出认为它在一个而不是另一个中,因此将其打印出来。所以输出看起来像这样:
A
B
B
C
E
E
etc.
这不是我所期待的。我正期待着
A
C
G
L
M
X
答案1
你可以在文件A中反向grep文件b的内容来做到这一点
例子 :
francois@zaphod:/tmp$
cat > A
az
ae
ar
at
ay
au
francois@zaphod:/tmp$
cat > b
ba
by
ay
at
au
francois@zaphod:/tmp$
grep -v "$(cat /tmp/b)" /tmp/A
az
ae
ar
francois@zaphod:/tmp$
这里的输出只是文件 A 中不存在于文件 b 中的行
答案2
Diff 输出显示文件 X 变成文件 Y 必须执行的操作。
根据您的评论,您可以使用以下 oneliner:
cat x y | sort -u | cat y - | sort | uniq -u
它会
- 读取两个文件
- 对它们进行排序并仅打印唯一的行(
-u
按顺序) - 读取文件 (y) 并将其与管道输出结合起来
- 度假村输出
- 使用 uniq 以便仅使用出现一次(
-u
唯一)的行。
该方法基于集合论。首先将两组相加,然后减去其中一组。
答案3
如果其中一个文件是 DOS 格式的文本文件,而另一个文件是 Unix 格式的文本文件,则每一行都将与另一个文件中的所有行不同,即使各行上的字母相同。这是由于一个文件中每一行末尾存在额外的回车字符,而另一个文件中不存在该字符。
我期望comm -3 file1 file2
when file1
is a Unix text file while file2
is a DOS text file 得到以下输出(这就是你所拥有的):
A
B
B
C
E
E
G
I
I
L
M
N
N
O
O
X
我期望comm -3 file1 file2
when file1
is a DOS text file while file2
is a Unix text file 得到以下输出:
A
B
B
C
E
E
G
I
I
L
M
N
N
O
O
X
如果两个文件具有相同的行结尾,即它们都是 DOS 文本文件或它们都是 Unix 文本文件,我期望的输出comm -3 file1 file2
是
A
C
G
L
M
X
您可以使用以下命令将这两个文件转换为 Unix 文本格式
dos2unix file1 file2
...假设您已经dos2unix
安装了该实用程序。