2012-04-27 13 views
2

"usb 1-3"と "address 20"の2つの値があります。今私は、これらの単語の両方を持つテキストファイル(基本的にログファイル)を検索しようとしています。Linuxで2番目に出現した単語の行を取得する

は今、そのファイルが、これらの言葉で多くの行を持っている:私はこれら二つの言葉の最後から2番目の発生と行を取得したいし、次の16:

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 

今私の要件は、ということですそれ以降の行。ファイル内に6つのオカレンスがある場合(この2つの単語の両方が6行の場合)、5番目のオカレンスとそれに続く16番目のラインが必要です。 10回の出現がある場合は、9回目の出現と次の16回の出現が必要です。

は、現在、私は

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

を使用していたが、それは私の最後の出現を与えます。最後まで2番目ではありません。私の質問が明確でないかどうか教えてください。 私の質問がはっきりしない場合は教えてください。前もって感謝します。

+0

"ユーザー不明" 私はあなたが実質的に変化したと思うし、質問を誤解。 http://stackoverflow.com/posts/10358234/revisions –

+0

私は物質を変更することなく質問を明確にすることに亀裂を入れました。 –

+0

あなたの努力をお寄せいただきありがとうございます。 – user115079

答えて

4

これには二つのパスが必要ですが、それはトリックを行う必要があります。

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

あなたは1回のパスでそれを行うにはawkまたはperlを使用することができますが、あなたには、いくつかのバッファを管理する必要があると思います。それは逆catであるtacを使用することに注意してください。システムにインストールしていない場合は、tail -rをその場所にドロップしてみてください。 perlを使用して

+0

申し訳ありませんが、正しく動作しません。ミックスタイプのラインがいくつか用意されています。私の必要条件ではありません...私の要件ログファイルでは、 "13:25:43"の行を示していますが、与えられた構文では私はいくつかの行13:16:29を得て、次にいくつかの行を得ます。 13:12:22 – user115079

+0

入力が表示されません。しかし、それがどのように機能するか説明しましょう。 ( 'egrep')、2番目から最後のマッチ(' tac'、 'sed')の行番号を取得し、その行番号から(' tail')にファイル全体をテールし、これらの行の最初の17行( 'head')を取り出します。たぶんあなたはあなたのデータでそれらのステップを試して、どこが間違っているのかを知ることができます。最初にgrepを確認してください。 –

+0

あなたが間違っているところを見ています。最初の部分は行番号を取得するのに完璧です。しかしその後、あなたが尻尾にしようとすると間違っています。例えば。私の場合は行番号119です。ここで "tail -119 filename"と入力すると、最後の119行が表示されます。ここで間違っています。最初の118行をスキップして、次の17行(その行を含む) – user115079

0

一つの方法:

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; 
    } 
} 
2

お持ちの場合はGNU grepの

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

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

+0

これは、パターンの最後の出現? –

+1

ここで何が起こったのか分かります。これは "ユーザー不明"という質問の第2版では最良のオプションですが、元の質問にはまったく対処していません。/10358234 /リビジョン –

関連する問題