【发布时间】:2013-10-26 11:21:59
【问题描述】:
我正在尝试比较两个文件的内容,这两个文件都只是一列数字,即
文件1:
1.2
2.6
3.4
4.7
5.3
文件2:
5.1
4.8
3.2
2.5
1.6
输出应该只是 file1 中大于 file2 中相应行的行数;所以在这种情况下它只是
3
【问题讨论】:
我正在尝试比较两个文件的内容,这两个文件都只是一列数字,即
文件1:
1.2
2.6
3.4
4.7
5.3
文件2:
5.1
4.8
3.2
2.5
1.6
输出应该只是 file1 中大于 file2 中相应行的行数;所以在这种情况下它只是
3
【问题讨论】:
这是一个仅使用 AWK 的解决方案,每次只从每个输入文件中读取一行。
BEGIN {
if (ARGC != 3)
{
print "Usage: this_program <file1> <file2>"
exit(1)
}
c = 0
for (;;)
{
result = getline < ARGV[1]
if (1 != result)
break
n1 = $1 + 0
result = getline < ARGV[2]
if (1 != result)
break
n2 = $1 + 0
if (n1 > n2)
++c;
}
print c
}
附:我是 Python 的粉丝,为了好玩,我也用 Python 解决了这个问题。
import sys
if sys.version_info.major < 3:
import itertools
zip = itertools.izip
with open(sys.argv[1]) as f1, open(sys.argv[2]) as f2:
print(sum(float(x) > float(y) for x, y in zip(f1, f2)))
注意事项:
zip() 对从两个来源读取的值进行配对。 zip(f1, f2) 对从两个输入文件中的每一个读取的行进行配对。
当您在 Python 2.x 上运行它时,我使用了 itertools.izip(),因此它一次只能处理一行。 Python 2 中内置的zip() 一次读取所有数据并构建一个列表。
错误检查并不明显,但确实存在。如果输入不能用作float 值,您将得到异常;如果用户没有指定至少两个输入文件,你会得到一个异常。
这使用了一个稍微低俗的技巧:sum() 会将布尔值 True 视为 1,将布尔值 False 视为 0。因此,这将获取所有行的计数> 比较为真。
【讨论】:
awk 单个进程可以完成这项工作:
awk 'NR==FNR{a[NR]=$0;next}a[FNR]>$0{i++}END{print i}' file1 file2
输出:
3
编辑
通过阅读 JonathanLeffler 和 steveha 的 cmets,我将添加另一个解决方案,以避免将怪物文件保存到内存中。仍然是单个 awk 进程:
awk '{getline x < "file2"}$0>x{i++}END{print i}' file1
输出:
3
【讨论】:
file1 读入内存。对于某些输入,这可能不切实际。
尝试使用paste,后跟awk
paste file1 file2 | awk '$1>$2 {i++} END {print i}'
输出:
3
【讨论】:
awk's) 内存中,因此它可以在需要时处理庞大的文件。缺点是通过管道移动所有数据的成本。
0 添加到$1 和$2 中,以强制它们转换为数字;否则,您可能会在某些输入上得到令人惊讶的结果。我刚刚测试过,只要输入以数字形式工作,AWK 似乎确实做了正确的事情,但表达式 100.3 < "abc" 在我测试时评估为 true。