如何基于 grep 搜索加速脚本?

use*_*494 5 grep shell-script text-processing

有一个非常大的文本文件,其中包含两个以逗号分隔的值:

78414387,10033
78769989,12668
78771319,13677
78771340,13759
80367563,16336
81634533,10025
82878571,10196
110059366,10218
110059411,10812
110059451,10067
Run Code Online (Sandbox Code Playgroud)

我需要在看起来像这样的日志文件中搜索这些值:

- delivery-AMC_prod_product 231825855936862016-07-02 00:00:52 c.c.i.d.s.d.DeliveryTopologyFactory$$anon$1$$anon$2 [INFO] ack: uid=57773c737e3d80d7def296c7| id=278832702| version=28| timestamp=1467432051000
- delivery-AMC_prod_product 231825855936862016-07-02 00:00:52 c.c.i.d.s.d.DeliveryTopologyFactory$$anon$1$$anon$2 [INFO] ack: uid=57773c732f18c26fe604fd04| id=284057302| version=9| timestamp=1467432051000
- delivery-AMC_prod_product 231825855936862016-07-02 00:00:52 c.c.i.d.s.d.DeliveryTopologyFactory$$anon$1$$anon$2 [INFO] ack: uid=57773c747e3d80d7def296c8| id=357229| version=1151| timestamp=1467432052000
- delivery-AMC_prod_product 231825855936862016-07-02 00:00:52 c.c.i.d.s.d.DeliveryTopologyFactory$$anon$1$$anon$2 [INFO] ack: uid=57773c742f18c26fe604fd05| id=279832706| version=35| timestamp=1467432052000
- delivery-AMC_prod_product 231825855936862016-07-02 00:00:52 c.c.i.d.s.d.DeliveryTopologyFactory$$anon$1$$anon$2 [INFO] ack: uid=57773c744697ddb976cf5a95| id=354171| version=503| timestamp=1467432052000
- delivery-AMC_prod_product 231825855936862016-07-02 00:00:53 c.c.i.d.s.d.DeliveryTopologyFactory$$anon$1$$anon$2 [INFO] ack: uid=57773c754697ddb976cf5a96| id=355638| version=1287| timestamp=1467432053000
Run Code Online (Sandbox Code Playgroud)

我的脚本:

#!/bin/bash
COUNT=0
while IFS=',' read ID VERSION; do
    VERSION=`echo $VERSION |col -bx`
    if (grep "id=${ID}| version=$VERSION" worker-6715.log.2016-$1.log.* > /dev/null); then
            let "COUNT++"
    else
            echo "$ID, $VERSION FAIL"
            exit 2

    fi
done < recon.txt

echo "All OK, $COUNT checked"
Run Code Online (Sandbox Code Playgroud)
  • 如果我从日志文件中删除不必要的字段,这会加快执行速度吗?
  • 如果我创建一个 RAM 设备并将日志文件复制到那里,这会加快执行速度还是我的Red Hat Linux 6 (Hedwig) 缓存文件?还有其他建议吗?

Sat*_*ura 5

您的瓶颈是recon.txt在 shell 中逐行读取文件。要获得失败的行,您可以预处理日志中的行,使其看起来像 中的行recon.txt,然后用于comm(1)查找设置的差异,可能如下所示:

comm -23 \
    <(sort -u recon.txt) \
    <(sed 's/.*| id=\([0-9]*\)| version=\([0-9]*\)|.*/\1,\2/' worker-6715.log.2016-$1.log.* | \
        sort -u)
Run Code Online (Sandbox Code Playgroud)

这假设有一个可以处理<(...)构造的 shell。另请注意,结果中的行不保留 中行的顺序recon.txt。保持这个顺序会更困难(而且更慢)。

如果您还需要成功计数,则可以反其道而行之,进行预处理recon.txt,使其看起来像在日志中找到的内容,然后使用fgrep(1)或grep -F进行搜索。将区域设置设置为 还C可以在某些系统上显着加快速度。因此:

COUNT=$( \
    sed 's/\([0-9]*\),\([0-9]*\)/| id=\1| version=\2|/' recon.txt | \
    LC_ALL=C fgrep -f - worker-6715.log.2016-$1.log.* | \
    wc -l )
Run Code Online (Sandbox Code Playgroud)

这假设recon.txt不包含重复项,并且每行在recon.txt所有日志中最多匹配一次。取消第一个限制将很困难。第二个可以通过仔细选择来解除comm(1)。

  • 好的。为什么这在 20 年或更长时间后仍然具有遥远的意义?当前(和以前)版本的 POSIX 规范明确定义了“grep -F”,并指出“*旧*[强调我的]egrep 和 fgrep 命令可能会作为实现扩展在未来很多年得到支持”。标准已经改变了,为什么还要继续使用老方法呢?为什么要继续生成遗留代码并迫使开发人员支持过时的命令?我们应该与时俱进,或者至少与时俱进地更新我们的建议。 (4认同)