优化 grep、awk 和 sed shell 内容

发布于 2024-09-03 21:33:29 字数 547 浏览 4 评论 0 原文

我尝试对来自“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 

现在我用以下命令 grep 包含端口 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 并不始终处于同一位置。

有什么优化这个命令的建议吗?

问候 雷内

I try to sum the traffic of diffrent ports in the logfiles from "IPCop" so i write and command for my shell, but i think its possible to optimize the command.

First a Line from my Logfile:

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 

Now i grep with following Command the sum of all lengths who contains port 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}'

The for loop i need because the LEN-col is not on same position at all time.

Any suggestion for optimizing this command?

Regards
Rene

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

温柔女人霸气范 2024-09-10 21:33:29

由于我没有代表向 Noufal Ibrahims 答案添加评论,因此这里有一个使用 Perl 的更自然的解决方案。

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

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

Since I don't have the rep to add a comment to Noufal Ibrahims answer, here is a more natural solution using Perl.

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

@Noufal you can can make perl do all the hard work ;).

枉心 2024-09-10 21:33:29

如果它确实需要优化,因为它运行得慢得难以忍受:您可能应该用更通用的语言重写它。即使 AWK 也可以,但我建议使用更接近 Perl 或 Java 的东西来实现长时间运行的提取器。

您可以进行的一个更改是,不要使用不必要的 SED 和第二个 AWK 调用,而是将 END 移到第一个 AWK 调用中,并使用 split() 从 LEN=num; 中提取数字;并将其添加到累加器中。像 split($i, x, "="); 之类的东西总和 += x[2]。

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

If it really needs optimization, as in it runs so unbearably slow: you should probably rewrite it in a more general purpose language. Even AWK could do, but I'd suggest something closer to Perl or Java for a long running extractor.

One change you could make is, rather than using an unnecessary SED and second AWK call, move the END into the first AWK call, and use split() to extract the number from LEN=num; and add it to the accumulator. Something like split($i, x, "="); sum += x[2].

The main problem is you can't write awk '/LEN=(...)/ { sum += var matching the ... }'.

你穿错了嫁妆 2024-09-10 21:33:29

只要管道中有 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

Any time you have grep/sed/awk combinations in a pipeline, you can simplify into a single awk or perl command. Here's an awk solution:

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
听不够的曲调 2024-09-10 21:33:29

如果您使用 gawk,则可以使用 \< 来避免使用 for 循环、match(-) 函数来查找子字符串“\” ",即投影出您想要的字段,并使用 substr 投影出 LEN 的参数。然后,您可以仅使用单个 awk 调用来完成所有操作。

后记

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

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

If you are using gawk, you can use \< to avoid the need for the for-loop, the match(-) function to find the substring "\<LEN=.*\>", i.e., projecting out the field you want, and substr to project out the argument of LEN. You can then use just the single awk invocation to do everything.

Postscript

The regexp I gave above doesn't work, because the = character is not part of a word. The following awk script does work:

/1433/ { f=match($0,/ LEN=[[:digit:]]+ /); v=substr($0,RSTART+5,RLENGTH-6); s+=v; }
END    { print "sum=" s; }
唱一曲作罢 2024-09-10 21:33:29

如果它们在一行上,您可以使用 perl 提取 LOG 数字并将其相加。

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

我为糟糕的 Perl 表示歉意。我根本不是 Perl 人。

If these will be on a single line, you can use perl to extract the LOG numbers and sum it.

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

I apologise for the bad Perl. I'm not a Perl guy at all.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文