2

「usb 1-3」と「address 20」の 2 つの値があります。今、これらの単語の両方を含むテキスト ファイル (基本的にはログ ファイル) を検索しようとしています。

そのファイルには、次のような単語を含む多くの行があります。

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

ここでの要件は次のとおりです。これらの 2 つの単語が最後から 2 番目に出現する行と、その次の 16 行を取得する必要があります。ファイルに6回出現する場合(これらの単語の両方を含む6行)のように、5番目に出現する行とその次の16行が必要です。10 回のオカレンスがある場合、9 回目のオカレンスと次の 16 行が必要です。

現在私が使用していた

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

しかし、それは私に最後の出現を与えます。最後から2番目ではありません。行には両方の単語が同じ順序で含まれている必要があることに注意してください(最初にusb 1-3、その後にアドレス20) 私の質問が明確でない場合は教えてください。前もって感謝します。

4

3 に答える 3

4

これには 2 つのパスが必要ですが、うまくいくはずです。

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

awkorを使用perlして 1 回のパスで実行することもできますが、いくつかのバッファーを管理する必要があります。を使用していることに注意してください。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 に答える