繁体   English   中英

优化grep,awk和sed shell的东西

[英]Optimize grep, awk and sed shell stuff

我试图从“IPCop”总结日志文件中的不同端口的流量,所以我为我的shell编写和命令,但我认为可以优化命令。

首先来自我的日志文件的一行:

01/00:03:16 kernel INPUT IN=eth1 OUT= MAC=xxx SRC=xxx DST=xxx LEN=40 TOS=0x00 PREC=0x00 TTL=98 ID=256 PROTO=TCP SPT=47438 DPT=1433 WINDOW=16384 RES=0x00 SYN URGP=0 

现在我用以下Command命令包含端口1433的所有长度的总和

grep 1433 log.dat|awk '{for(i=1;i<=10;i++)if($i ~ /LEN/)print $i};'|sed 's/LEN=//g;'|awk '{sum+=$1}END{print sum}'

我需要for循环,因为LEN-col始终不在同一位置。

有关优化此命令的任何建议吗?

关心雷内

由于我没有代表为Noufal Ibrahims回答添加评论,这是使用Perl的更自然的解决方案。

perl -ne '$sum += $1 if /LEN=(\d+)/; END { print $sum; }' log.dat

@Noufal你可以让perl做所有艰苦的工作;)。

如果它真的需要优化,就像它运行得如此缓慢:你应该用更通用的语言重写它。 即使是AWK也可以这样做,但我建议使用更接近Perl或Java的长期运行提取器。

你可以做的一个改变是,不是使用不必要的SED和第二次AWK调用,而是将END移动到第一个AWK调用中,并使用split()从LEN = num中提取数字。 并将其添加到累加器。 像split这样的东西($ i,x,“=”); sum + = x [2]。

主要问题是你不能写awk'/ LEN=(...)/ {sum + = var匹配...}'。

只要在管道中有grep / sed / awk组合,就可以简化为单个awk或perl命令。 这是一个awk解决方案:

gawk -v dpt=1433 '
    $0 ~ dpt {
        for (i=1; i<=NF; i++) {
            if ($i ~ /^LEN=[[:digit:]]+/) {
                split($i, ary, /=/)
                sum += ary[2]
                next
            }
        } 
    } 
    END {print sum}
' log.dat

如果你正在使用gawk,你可以使用\\<来避免需要for循环,匹配( - )函数来找到子串“\\ <LEN =。* \\>”,即投出你想要的字段和substr来计算出LEN的参数。 然后,您可以使用单个awk调用来执行所有操作。

后记

我上面给出的正则表达式不起作用,因为=字符不是单词的一部分。 以下awk脚本确实有效:

/1433/ { f=match($0,/ LEN=[[:digit:]]+ /); v=substr($0,RSTART+5,RLENGTH-6); s+=v; }
END    { print "sum=" s; }

如果这些将在一行上,您可以使用perl提取LOG编号并对其求和。

perl -e '$f = 0; while (<>) {/.*LEN=([0-9]+).*/ ; $f += $1;} print "$f\n";' input.log

我为糟糕的Perl道歉。 我根本不是Perl的人。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM