帮助我使用命令(主要是 awk)

帮助我使用命令(主要是 awk)

我刚刚写了我写过的最扭曲的命令,我想知道如何才能使它变得更好。

我写了这个:

grep -E '00[7-9]\.|0[1-9][0-9]\.' filename.log | awk '{print $6}' | sed 's/\(.*\):.*/\1/' | sort | uniq -c | sort -rn

输入示例:

2011/06/30 07:59:43:81 20626 code_file.c (252): FunctionName: 009.63 seconds

它所做的基本上是查看一个日志文件,该文件列出了命令执行所花费的秒数,并抓取其中执行时间在 7 到 99 秒之间的任何命令。然后 awk 打印第六个单词,即函数名称后跟一个冒号。然后 sed 删除冒号和任何尾随空格,然后对其进行排序、计数,然后根据计数进行排序。

我使用的是 HP-UX,因此某些工具功能有限,但我知道 awk 可以完成我刚刚用 sed 完成的操作。有人能帮我简化命令吗?

答案1

awk '/00[7-9]\.|0[1-9][0-9]\./ { # for lines matching the regex
       split($6, c, /:/)         # take the part of field 6 before the colon
       cs[ c[1] ]++              # and increment the counter for that string
     }
     END {                       # after all lines have been read
       for (c in cs) {           # step through the counters
         print cs[c], c          # and output the count followed by the string
                                 #   ("," adds a space automatically)
       }
     }' filename.log | sort -rn  # standard awk doesn't support sorting, sadly

我继续对如此多的人感到惊讶,他们显然认为 either awknorsed不能进行模式匹配,所以他们必须添加grep调用。

答案2

我是所以将会因这个而被否决......

#!/usr/bin/env perl
use strict;

my %counts;
while (my $line = <>) {
    my @line = split(/\s+/, $line);
    if ($line[6] >= 7) {
        $line[5] =~ /(.+):/ and $counts{$1}++;
    }
}

my @sorted = sort {$counts{$b} <=> $counts{$a}} keys %counts;

printf("%7d\t%s\n", $counts{$_}, $_) for @sorted;

答案3

您的命令有点脆弱,因为如果文件名中有空格,它将失败。除此之外,您的命令实际上还不错。这在某种程度上是一个品味问题,但我发现一串简单的管道命令比一个复杂的命令(例如某人发布的大型 awk)更容易理解。它几乎可能是以函数式风格进行编程。

但是,您可以更改 grep 以消除 awk 和 sed,但现在正则表达式变得更难理解:


grep -P -o '(?<=\): ).+?(?=: 00[7-9]|0[1-9]|1)' | sort | uniq -c | sort -nr

为了解释正则表达式,我们使用 perl 样式 re (-P param),并使用后视 (?<=) 和前视 (?=) 将匹配项精确地隔离到函数名称。请注意,后视和前视是零宽度,这意味着它们不被视为匹配项的一部分,但控制匹配项的实际内容。由于匹配项现在精确地是函数名称,我们可以使用 -o 来告诉 grep 仅打印匹配的字符串而不是整行。我认为你应该保留你所拥有的,除非你认为文件名带有空格是可能的。

答案4

当我这样做的时候:

#!/bin/sh
grep -E '00[7-9]\.|0[1-9][0-9]\.' "$@" | awk '{print $6}' |
    sed 's/:$//' | sort | uniq -c | sort -rn

原始命令并不复杂,只是每个日志的重复才让它看起来如此。将它粘贴到脚本文件(或函数)中,调用它sortbytime,这样你就有了一个简单的单词命令。

相关内容