您的解决方案实际上可能很慢,因为它创建了 50.000 个进程,所有进程都读取 500 行模式文件。
另一个“纯 bash 和 unix utils”解决方案可能是让它grep
做它最擅长的事情,并将输出与你的 pattern_file 匹配。
所以使用grep
来查找匹配的行和实际匹配的部分。
我在这里使用单词匹配,可以通过删除 grep 行中的开关来关闭它,-w
并获得示例中描述的初始行为。
输出尚未重定向到result_file.csv
.. 这很容易在以后添加 8)
#!/bin/bash
# open pattern_file
exec 3<> pattern_file
# declare and initialize integer variables
declare -i linenr
declare -i pnr=0
# loop for reading from the grep process
#
# grep process creates following output:
# <linenumber>:<match>
# where linenumber is the number of the matching line in pattern_file
# and match is the actual matching word (grep -w) as found in lookup_file
# grep output is piped through sed to actually get
# <linenumber> <match>
while read linenr match ; do
# skip line from pattern_file till we read the line
# that contained the match
while [[ ${linenr} > ${pnr} ]] ; do
read -u 3 pline
pnr+=1
done
# echo match and line from pattern_file
echo "$match, $pline"
done < <( grep -i -w -o -n -f lookup_file pattern_file | sed -e 's,:, ,' )
# close pattern_file
exec 3>&-
结果是
sun, The sun is shining
shining, The sun is shining
beautiful, It is a beautiful day!
对于给出的例子。注意:匹配现在是保留大小写的完全匹配。所以这不会导致Sun, ...
但会导致sun, ...
.
结果是一个脚本,它使用 grep 读取 pattern_files 一次,在最好的情况下读取 pattern_file 和 lookup_file 一次 - 取决于实际实现。它只会启动两个额外的进程:grep
和sed
. (如果需要,sed
可以用外循环中的一些 bash 替换来替换)
我没有尝试使用 50.000 行 lookup_file 和 500 行 pattern_file。但我认为它可能和 grep 一样快。
只要grep
可以将lookup_file保存在内存中,它可能是合理的快。(谁知道)
无论它是否解决了您的问题,我都会对它与您的初始脚本相比的性能感兴趣,因为我确实缺少很好的测试文件。
如果grep -f lookup_file
使用太多内存(正如您之前在评论中提到的),它可能是一种解决方案,可以将其拆分为实际适合内存的部分并多次运行脚本或使用不止一台机器,在这些机器上运行所有部分并且只是收集并连接结果。只要 lookup_files 不包含欺骗,您就可以连接结果而不检查欺骗。如果排序很重要,您可以对所有单个结果进行排序,然后使用sort -m
.
只要您只拆分一次lookup_file 并重新运行脚本,拆分lookup_file 不会显着影响运行时间,因为您的pattern_file 可能足够小,它的500 行无论如何都可以保留在内存缓存中!?如果您使用多于一台机器,lookup_file 可能也是如此 - 它的部分可能只保留在每台机器的内存中。
编辑:
正如我在评论中指出的那样,这不适用于开箱即用的重叠文件,因为grep -f
似乎只返回最长的匹配并且不会重新匹配,所以如果lookup_file
包含
Sun
Shining
is
S
结果将是
sun, The sun is shining
is, The sun is shining
shining, The sun is shining
并不是
sun, The sun is shining
is, The sun is shining
shining, The sun is shining
s, The sun is shining
s, The sun is shining
s, The sun is shining
因此,所有匹配项s
(匹配三次)都丢失了。
事实上,这是这个解决方案的另一个问题:如果一个字符串被找到两次,它将被匹配两次,并且将返回相同的行,这可以通过uniq
.
可能的解决方法:拆分lookup_file
搜索字符串的按字符串长度。这将减少运行 grep 所需的最大内存,但也会稍微减慢整个过程。但是:然后您可以并行搜索(如果在同一台服务器上执行此操作,可能需要检查grep
s选项)。--mmap