使用bash脚本(Ubuntu 16.04),我试图比较2个范围列表:file1中任何范围内的任何数字是否与file2中任何范围内的任何数字一致?如果是这样,请在第二个文件中打印该行 . 这里我将每个范围作为2个制表符分隔的列(在file1中,第1行表示范围1-4,即1,2,3,4) . 真实的文件非常大 .
文件1:
1 4
5 7
8 11
12 15
文件2:
3 4
8 13
20 24
期望的输出:
3 4
8 13
我最好的尝试是:
awk 'NR=FNR { x[$1] = $1+0; y[$2] = $2+0; next};
{for (i in x) {if (x[i] > $1+0); then
{for (i in y) {if (y[i] <$2+0); then
{print $1, $2}}}}}' file1 file2 > output.txt
这将返回一个空文件 .
我认为脚本需要使用if-then条件进行范围比较,并遍历两个文件中的每一行 . 我找到了每个概念的例子,但无法弄清楚如何将它们结合起来 .
任何帮助赞赏!
6 回答
对于GNU awk,因为我正在控制
for
扫描顺序以优化时间:测试数据:
输出:
和
如果Perl解决方案是首选,那么下面的单行程将起作用
分解:
基本上我们在处理第一个文件时设置file = 1,在处理第二个文件时设置file = 2 . 当我们在第一个文件中时,将该行读入键入该行的每个字段的数组中 . 当我们在第二个文件中时,处理数组(nums)并检查该行上每个字段是否有条目 . 如果有,请打印 .
awk 解决方案:
输出:
当然,这取决于你的文件有多大 . 如果它们不足以耗尽内存,您可以尝试这种100%bash解决方案:
这只是一个起点 . 有许多可能的性能/内存占用改进 . 但它们在很大程度上取决于文件的大小和范围的分布 .
EDIT 1 :改进了范围重叠测试 .
EDIT 2 :重复使用RomanPerekhrest提出的优秀优化(未设置已打印的范围来自
file2
) . 当范围重叠的概率很高时,性能应该更好 .EDIT 3 :与RomanPerekhrest提出的
awk
版本的性能比较(修复了最初的小错误之后):awk
在此问题上比bash
快10到20倍 . 如果表现很重要且你在awk
和_37471之间犹豫不决,请选择:如果范围是根据其下限排序的,我们可以使用它来使算法更有效 . 这个想法是,如果file1的某些间隔低于file1当前观察到的间隔,它们肯定低于file1中的下一个间隔,因此我们不需要检查与较低间隔的交点 .
可以使用
./script.sh file2 file1
调用该脚本