如何在UNIX中逐行比较两个不同的文件?


13

文件1:

123
234
345
456

文件2:

123
234
343
758

预期输出:File3:

TRUE
TRUE
FALSE
FALSE

因此,代码应比较两个文件,如果匹配则打印“ TRUE”,否则应在新文件中打印“ FALSE”。有人可以为此提供解决方案吗?


10
如果两个文件的长度不相等怎么办?您在此问题的解决方案的哪一部分遇到问题?
库萨兰达

9
您可能想看看diff
Panki

2
在这些情况下,其他有用的命令是comm。这样就很容易列出两个文件共有的行或一个文件对另一个行是唯一的行。
Giacomo Alzetta

1
@GiacomoAlzetta的问题comm是,它需要排序的输入。除了问题的示例确实对输入进行了排序外,问题从未断言这是正在使用的实际数据,也从未说过有关数据排序的任何信息。
Kusalananda

2
αғsнιη的nl技巧可comm用于对文件强加排序。
glenn jackman

Answers:


56

使用diff命令如下,在bash或任何其他外壳支持<(...) 处理替代或者你可以模仿它,如下所示

diff --new-line-format='FALSE'$'\n' \
     --old-line-format='' \
     --unchanged-line-format='TRUE'$'\n' \
<(nl file1) <(nl file2)

输出为:

TRUE
TRUE
FALSE
FALSE

--new-line-format='FALSE'$'\nFALSE如果行不同则打印,如果文件1的行不同,--old-line-format=''则禁用输出,这称为文件到diff命令(我们也可以交换它们,这意味着其中一个应打印FALSE另一行应被禁用。)

--unchanged-line-format='TRUE'$'\n'TRUE如果行相同则打印。在$'\n'C语言风格的逸出语法用于打印每行输出后一个新行。


24

假设文件不包含制表符:

$ paste file1 file2 | awk -F '\t' '{ print ($1 == $2 ? "TRUE" : "FALSE") }'
TRUE
TRUE
FALSE
FALSE

这用于paste创建两个制表符分隔的列,两个文件的内容均位于任一列中。该awk命令比较每行上的两列,TRUE如果列相同则打印,否则进行打印FALSE


10

假设两个文件的行数相同:

awk '{getline f2 < "file2"; print f2 == $0 ? "TRUE" : "FALSE"}' file1

如果要比较的字符串为数字,则为数字比较,否则为词法比较。例如,100并且1.0e2将被视为相同。更改为f2"" == $0在任何情况下都强制进行词法比较。

根据awk实现的不同,词汇比较将通过使用memcmp()(逐字节比较)还是通过使用strcoll()(两个字符串是否按语言环境的整理顺序排序相同)来完成。这可能会在某些语言环境中有所不同,在某些语言环境中,某些字符的顺序未正确定义,而不是示例中的所有十进制数字输入。


7

Python 3

with open('file1') as file1, open('file2') as file2:
    for line1, line2 in zip(file1, file2):
        print(line1 == line2)

输出:

True
True
False
False

如果需要TRUE,请FALSE大写将打印行替换为以下之一:

print(str(line1 == line2).upper())
print('TRUE' if line1 == line2 else 'FALSE')

2
在Python 2中,import itertools先执行,然后使用itertools.izip代替zip。否则,它将两个文件都读取到内存中,可能会占用过多的内存。
pts

4

在中bash,从while循环中读取每个文件,比较读取的行并打印TRUEFALSE适当地进行以下操作:

while IFS= read -r -u3 line1; IFS= read -r -u4 line2; do
    [[ $line1 == $line2 ]] && echo TRUE || echo FALSE
done 3<file1 4<file2

这两个调用read分别从文件描述符3和4读取。通过两次输入重定向将文件重定向到这些文件。


0
Tried with awk command and it worked fine


awk 'NR==FNR{a[$1];next}{if ($1 in a){print "TRUE"} else{print "False"}}' file1 file2

输出

TRUE
TRUE
False
False
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.