mar*_*rio 5 grep bash large-files algorithms
我有超过 300K 行的 FILE_A 和超过 30M 行的 FILE_B。我创建了一个 bash 脚本,它将 FILE_A 中的每一行 grep 到 FILE_B 中,并将 grep 的结果写入一个新文件。
整个过程需要超过 5 个多小时。
我正在寻找有关您是否看到任何提高脚本性能的方法的建议。
我使用 grep -F -m 1 作为 grep 命令。FILE_A 看起来像这样:
123456789
123455321
Run Code Online (Sandbox Code Playgroud)
和 FILE_B 是这样的:
123456789,123456789,730025400149993,
123455321,123455321,730025400126097,
Run Code Online (Sandbox Code Playgroud)
因此,使用 bash 我有一个 while 循环,它选择 FILE_A 中的下一行,并在 FILE_B 中将其遍历。当在 FILE_B 中找到模式时,我将其写入 result.txt。
while read -r line; do
grep -F -m1 $line 30MFile
done < 300KFile
Run Code Online (Sandbox Code Playgroud)
非常感谢您的帮助。
性能的关键是只读取一次大文件。
您可以通过将多个模式放在单独的行上来将多个模式传递给 grep。这通常是通过告诉 grep 从文件中读取模式来完成的:
grep -F -f 300KFile 30MFile
Run Code Online (Sandbox Code Playgroud)
这会按照大文件的顺序输出匹配项,并且只打印一次匹配多个模式的行。此外,这会查找行中任何位置的模式;例如,如果模式文件包含1234
,则诸如123456,345678,2348962342
和 之类的478912,1211138,1234
行将匹配。
您可以通过预处理模式来限制精确的列匹配。例如,如果模式不包含任何特殊字符()?*+\|[]{}
:
<300KFile sed -e 's/^/(^|,)/' -e 's/$/($|,)/' |
grep -E -f - 30MFile
Run Code Online (Sandbox Code Playgroud)
如果仅保留每个模式的第一个匹配项很重要,则进行第一遍以仅提取上述相关行,然后在 awk 或 perl 中进行第二遍跟踪已经看到的模式。
<300KFile sed -e 's/^/(^|,)/' -e 's/$/($|,)/' |
grep -E -f - 30MFile |
perl -l -F, -ape '
BEGIN {
open P, "300KFile" or die;
%patterns = map {chomp; $_=>1} <P>;
close P;
}
foreach $c (@F) {
if ($patterns{$c}) {
print;
delete $patterns{$c};
}
}
'
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
12977 次 |
最近记录: |