改善Shell脚本性能

rjs*_*ing 1 regex unix shell performance grep

此shell脚本用于从$2包含模式的数据中提取数据行$line.

$line使用正则表达式[A-Z0-9.-]+@[A-Z0-9.-]+(简单的电子邮件匹配)构造,在文件中形成行$1.

#! /bin/sh

clear

for line in `cat "$1" | grep -i -o -E "[A-Z0-9.-]+@[A-Z0-9.-]+"`
do
    echo `cat "$2" | grep -m 1 "\b$line\b"`
done
Run Code Online (Sandbox Code Playgroud)

文件$1有短行数据(<100个字符),包含大约.50k线(约1-1.5 MB).

文件$2的文本行稍长(> 80到<200),并且有2M +行(约200MB).

运行的台式机具有足够的RAM(6 Gig)和具有2-4个内核的Xenon处理​​器.

是否有任何快速修复以提高性能,因为目前需要1-2小时才能完全运行(并输出到另一个文件).

注意:我对所有建议持开放态度,但我们不能复杂地重写整个系统等.此外,数据来自第三方,并且易于随机格式化.

Joh*_*ica 7

快速建议:

  1. 避免无用的使用cat和更改cat X | grep Ygrep Y X.

  2. 您可以grep通过管道输出来处理输出,而不是使用反引号.使用反引号需要先grep完成后才能启动第二个grep.

从而:

grep -i -o -E "[A-Z0-9.-]+@[A-Z0-9.-]+" "$1" | while read line; do
    grep -m 1 "\b$line\b" "$2"
done
Run Code Online (Sandbox Code Playgroud)

下一步:

  1. 不要$2重复处理.很大.您可以保存所有模式,然后对文件执行单个grep.
  2. sed.替换循环.

不再重复grep:

grep -i -o -E "[A-Z0-9.-]+@[A-Z0-9.-]+" "$1" | sed -E 's/^|$/\\1/g' > patterns
grep -f patterns "$2"
Run Code Online (Sandbox Code Playgroud)

最后,使用一些bash幻想(参见man bash→流程替换),我们可以抛弃临时文件,并在一个长行中执行此操作:

grep -f <(grep -i -o -E "[A-Z0-9.-]+@[A-Z0-9.-]+" "$1" | sed -E 's/^|$/\\b/g') "$2"
Run Code Online (Sandbox Code Playgroud)

除非你有很多模式grep -f用完内存和barf,否则这很好.如果发生这种情况,您需要批量运行它.讨厌,但可行:

grep -i -o -E "[A-Z0-9.-]+@[A-Z0-9.-]+" "$1" | sed -E 's/^|$/\\1/g' > patterns

while [ -s patterns ]; do
    grep -f <(head -n 100 patterns) "$2"
    sed -e '1,100d' -i patterns
done
Run Code Online (Sandbox Code Playgroud)

那将一次处理100个模式.它可以立即做的越少,你的第二个文件所需的传递次数就越少.