2

我有两个值“usb 1-3”和“地址 20”。现在我正在尝试搜索一个包含这两个词的文本文件(基本上是一个日志文件)。

现在该文件有很多行,其中包含以下单词:

Apr 27 13:30:55 box2 kernel: usb 1-3: USB disconnect, address 20
and
Apr 27 13:25:43 box2 kernel: usb 1-3: new high speed USB device using ehci_hcd and address 20

现在我的要求是:我想得到这两个单词倒数第二次出现的那一行,然后是接下来的 16 行。就像文件中有 6 次出现(这两个词都出现 6 行),那么我需要第 5 次出现的行和接下来的 16 行。如果有 10 次出现,那么我需要第 9 次出现和接下来的 16 行。

目前我正在使用

egrep -A 20 'usb 1-3:.*address 20' filename | tail -16 > output.

但它给了我最后一次出现。不是倒数第二个。请注意,该行应该有两个单词并且顺序相同(首先是usb 1-3,然后是地址20)如果我的问题不清楚,请告诉我。提前致谢。

4

3 回答 3

4

这需要两次通过,但它应该可以解决问题:

tail -n +`egrep -n 'usb 1-3:.*address 20' filename |
  tac | sed -n '2s/:.*//p'` filename | head -17

您可以使用awkperl一次性完成,但您需要管理一些缓冲区。请注意,它使用tac的是反向cat。如果您的系统上没有它,请尝试tail -r替换它。

于 2012-04-27T21:58:23.940 回答
2

如果你有 GNU grep

grep -B 1 -A 15 'usb 1-3.*address 20' filename

http://manpages.debian.net/cgi-bin/man.cgi?query=grep

于 2012-04-27T22:58:10.010 回答
0

一种使用方式perl

use warnings;
use strict;

die qq[Usage: perl $0 <input-file>\n] unless @ARGV == 1;

my (@lines, $found);

## Reverse content and pipe output to perl.
open my $fh, q[-|], qq{tac $ARGV[0]} or die qq[Open error: $!\n];

## Read line by line.
while ( <$fh> ) { 

    ## Remove trailing '\n'.
    chomp;

    ## Use an array as a FIFO structure and save last 16 lines
    ## processed.
    if ( @lines > 16 ) { 
        pop @lines;
    }   
    unshift @lines, $_; 

    ## Count how many lines matches at same time 'usb 1-3' and
    ## 'address 20'.
    if ( m/usb\s1-3/ && m/address\s20/ ) { 
        ++$found;
    }   

    ## In second one, print lines saved.
    if ( ($found || 0) == 2 ) { 
        printf qq[%s\n], join qq[\n], @lines; 
    }   
}
于 2012-04-27T22:28:52.533 回答