【问题标题】:awk to print header and lines matching specific criteriaawk 打印符合特定条件的标题和行
【发布时间】:2014-11-25 13:55:13
【问题描述】:

我正在打印 iostat 或类似的输出,例如:

[/] # iostat -xnCT d 5 5
Tue Nov 25 13:45:56 2014
                    extended device statistics
    r/s    w/s   kr/s   kw/s wait actv wsvc_t asvc_t  %w  %b device
    0.0    0.0    0.0    0.0  0.0  0.0    0.0    3.1   0   0 c0
    0.0    0.0    0.0    0.0  0.0  0.0    0.0    3.1   0   0 c0t0d0
    0.1    2.7    1.6    4.8  0.0  0.0    0.1    433.2   0   0 c1
    0.1    2.7    1.5    4.8  0.0  0.0    0.1    3.3   0   0 c1t0d0
    0.0    0.0    0.0    0.0  0.0  0.0    0.0    100.1   0   0 c1t1d0
    0.0    0.0    0.0    0.0  0.0  0.0    0.0    0.0   0   0 c1t2d0
    0.0    0.0    0.0    0.0  0.0  0.0    0.0    0.5   0   0 c1t3d0
    0.1    0.1    0.1    0.0  0.0  0.0    0.0    600.0   0   0 c2
    0.0    0.0    0.0    0.0  0.0  0.0    185.0    0.0   0   0 c2t0d0
    0.0    0.0    0.0    0.0  0.0  0.0    0.0    0.0   0   0 c2t1d0
    0.0    0.0    0.0    0.0  0.0  0.0    0.0    0.1   0   0 c2t4d0
    0.0    0.0    0.0    0.0  0.0  0.0    295.0    0.0   0   0 c2t5d0
    0.0    0.0    0.0    0.0  0.0  0.0    0.0    0.1   0   0 c2t6d0
    0.0    0.0    0.0    0.0  0.0  0.0    0.0    0.0   0   0 c2t8d0
    0.0    0.0    0.0    0.0  0.0  0.0    0.0    0.0   0   0 c2t9d0
    0.0    0.0    0.0    0.0  0.0  0.0    0.0    0.0   0   0 c2t10d0
    0.0    0.0    0.0    0.0  0.0  0.0    0.0    0.1   0   0 c2t11d0
    0.0    0.0    0.0    0.0  0.0  0.0    0.0    0.0   0   0 c2t12d0
    0.1    0.1    0.0    0.0  0.0  0.0    0.0    0.0   0   0 c3
    0.0    0.0    0.0    0.0  0.0  0.0    0.0    0.0   0   0 c3t0d0
    0.0    0.0    0.0    0.0  0.0  0.0    0.0    0.0   0   0 c3t1d0
    0.0    0.0    0.0    0.0  0.0  0.0    0.0    0.0   0   0 c3t2d0
    0.0    0.0    0.0    0.0  0.0  0.0    0.0    0.0   0   0 c3t3d0
    0.0    0.0    0.0    0.0  0.0  0.0    0.0    0.0   0   0 c3t4d0
    0.0    0.0    0.0    0.0  0.0  0.0    0.0    0.0   0   0 c3t5d0
    0.0    0.0    0.0    0.0  0.0  0.0    0.0    0.0   0   0 c3t6d0
    0.0    0.0    0.0    0.0  0.0  0.0    0.0    0.0   0   0 c3t8d0

我生成这些日志,然后使用脚本打印出信息。现在我正在研究一些我需要的性能脚本,例如,从一直生成的日志文件中 grep 查找具有较高平均服务时间的值,并查看例如大于 100 的值。

所以这是我能做的:

awk '$7 > 100 || $8 > 100' filename

因此,我将获取 wsvc_t 和 asvc_t 的值大于 100 的所有条目。注意,这只是一个示例。但是,我还想打印发生这种情况的日期,这无法使用 grep -B 完成,或者我不确定如何使用 sed 或 awk 来执行此操作,因为条目之前的行数不会是固定的一。

那么有没有一种简单的方法可以做到这一点,我可以以 7 美元或 8 美元的价格打印值大于 100 的行,然后在找到的条目上方打印具有 2014 年或年份的行?

所以我的结果应该是这样的:

Tue Nov 25 13:45:56 2014
                    extended device statistics
    r/s    w/s   kr/s   kw/s wait actv wsvc_t asvc_t  %w  %b device
    0.1    2.7    1.6    4.8  0.0  0.0    0.1    433.2   0   0 c1
    0.0    0.0    0.0    0.0  0.0  0.0    0.0    100.1   0   0 c1t1d0
    0.1    0.1    0.1    0.0  0.0  0.0    0.0    600.0   0   0 c2
    0.0    0.0    0.0    0.0  0.0  0.0    185.0    0.0   0   0 c2t0d0
    0.0    0.0    0.0    0.0  0.0  0.0    295.0    0.0   0   0 c2t5d0

日志文件将运行数千行。

【问题讨论】:

  • 对于这个输入,awk 'NR<=3 || $7 > 100 || $8 > 100' file 会成功。这将打印前 3 行,然后打印符合您条件的行。
  • 如果一个文件中可以包含多个日期,并且您需要捕获额外的日期标题 awk 'NF < 7 || $7 > 100 || $8 > 100' file 会这样做。
  • @EtanReisner 虽然它不会打印列标题(我实际上还没有尝试过)。现在试了一下,为什么“wsvc_t”超过100哈哈。实际上为什么它总是等同的无论使用什么数字都为真?
  • @fedorqui 是的,字符串比较(这是 awk 在那里所做的,至少对于 gawk 而言)是比较字符值并且数字都小于字母。标点符号更有趣,因为其中一些“大于”数字,而一些“小于”数字。
  • @fedorqui :请给出答案。

标签: bash perl shell awk sed


【解决方案1】:

我会使用以下内容:

awk 'NR<=3 || $7 > 100 || $8 > 100'

这将打印符合以下任一条件的行:

  • NR&lt;=3NR 代表记录数,通常是行数。因此,我们正在寻找小于或等于 3 的行号(以打印标题)。
  • 第 7 个字段严格大于 100。这是您已经拥有的。
  • 第 8 个字段严格大于 100。这是您已经拥有的。

所以我添加到您当前脚本中的唯一内容是NR&lt;=3,当确切知道我们要打印的行号时,它非常有用,就像现在一样。

测试

将给定的输入存储为文件:

$ awk 'NR<=3 || $7 > 100 || $8 > 100' file
Tue Nov 25 13:45:56 2014
                    extended device statistics
    r/s    w/s   kr/s   kw/s wait actv wsvc_t asvc_t  %w  %b device
    0.1    2.7    1.6    4.8  0.0  0.0    0.1    433.2   0   0 c1
    0.0    0.0    0.0    0.0  0.0  0.0    0.0    100.1   0   0 c1t1d0
    0.1    0.1    0.1    0.0  0.0  0.0    0.0    600.0   0   0 c2
    0.0    0.0    0.0    0.0  0.0  0.0    185.0    0.0   0   0 c2t0d0
    0.0    0.0    0.0    0.0  0.0  0.0    295.0    0.0   0   0 c2t5d0

【讨论】:

    【解决方案2】:

    您需要在它们经过时将有趣的标头数据捕获到变量中。然后,当看到一堆有趣的行时,您需要选择打印一次标题。最后,您需要重置每次看到新日期时都会打印标题这一事实。

    您的首选语言是什么?我不了解 awk 当前关于模式的能力;当我开始使用 Perl 时,我就不再关心了。所以这里有一些 Perl 代码我在没有测试的情况下就完成了:

    source-process-feeding-lines | perl -n -e '
        if(/^(\w+ \w+ \d+ \d+:\d+:\d+ \d+)$/) {
            $date = $1;
            $header1 = $header2 = $printed = undef;    # reset heading state
            continue;    # next line please
        }
    
        if(/extended device statistics/) {
            $header1 = $_;
            continue;
        }
    
        if(/^(\s*\w\/\w.*device)$/ {   # simple but probably sufficient recogniser
            $header2 = $_;
            continue;
        }
    
        # assume a data line here
        if(/your pattern for an interesting line/) {
            if(! $printed) {
                $printed = 1;     # prevent a 2nd printing unless the date changes
                print $date, $header1, $header2;
            }
    
            print;    # print your interesting line
        }
    '
    

    这与我认为您要问的很接近。调试可能需要申请!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-09-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-03-25
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多