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


2

我只是写了我写过的最歪曲的命令,我想知道如何做得更好。

我这样写:

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的工作。有人可以帮助我简化我的命令吗?


输入行示例将很有帮助。
grawity 2011年

您提到您的工具有限,可以详细说明吗?例如,由于Gravity的答案是perl,您有perl吗?
bbaja42 2011年


我有perl。我只是在说HP-UX工具的功能通常少于GNU计数器的功能。例如,HP-UX的grep缺少-rab和许多更重要的选项,也没有uniq的-w等
Malfist

Answers:


3
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

令我感到惊讶的是,许多人似乎都不相信模式匹配,awksed无法进行模式匹配,因此他们不得不添加一个grep调用。


您是否愿意将其分解?我不完全了解你在做什么。
Malfist 2011年

第一个节:在与正则表达式匹配的任何行上,在冒号上拆分字段6并根据第一个组件增加一个计数器(这与您的重复sed)。(awk与普通数组相比,数组更像Perl哈希或Python字典。)第二节在读取所有行之后执行,并打印出数组中的项目和计数;这代替了sort | uniq -c零件。我可以分界线并添加一些评论。
geekosaur 2011年

1

所以要被downvoted这个...

#!/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;

这几乎不是命令吗?:p
BloodPhilia 2011年

@BloodPhilia:我每天使用的一半命令看起来像这样。(另一半是bash和Python。)我本可以将它写成perl -ne单行,但是相比之下,它几乎是不可能理解的。
grawity 2011年

2
Perl可以是SuperUser的jQuery。;-)
修补

1

您的命令有点脆弱,因为如果文件名中有空格,它将失败。否则,您的命令实际上还不错。这有点有点问题,但是我发现一连串简单的管道命令比一个复杂的命令(例如有人发布的大型awk)更容易理解。很有可能以功能风格进行编程。

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


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

为了解释正则表达式,我们使用perl样式re(-P param)并使用look back(?<=)和look-ahead(?=)将匹配完全隔离到函数名。请注意,先行查找和先行宽度为零,这意味着它们不被视为匹配的一部分,而是控制实际匹配的内容。由于现在匹配项正好是函数名,因此我们可以使用-o告诉grep仅打印匹配的字符串,而不打印整个行。我认为您应该保留现有的文件,除非您认为使用空格的文件名是可能的。


0

在我的时候:

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

原始命令并不那么复杂,它是每个日志的重复使它看起来如此。将其粘贴到脚本文件(或函数)中,调用它sortbytime,然后在这里–您有一个简单的单字命令。


是否出于某些原因需要单独回答?
nhinkle

@nhinkle:可能不是。随时删除它。(我应该合并它们,但不能使用手机的浏览器来完成。)
grawity 2011年

这是两个不同的答案。如果有人喜欢这个,而另一个不喜欢,他们可以那样投票。如果将它们合并,则不能合并。要么全有要么全无。
Malfist 2011年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.