2017-01-18 16 views
-4

私はファイルの検索と近接検索

  • は、いずれかのライン上の両方pathredirectを持つファイルを探して、私はbashの端子を使用していgrep a file, but show several surrounding lines?

    で見てきた

  • 付近の行にflashがあります。先頭から5行以内

これはgrep、ag、Perl、sed、またはあなたが知っているツールで可能ですか?

+0

としてこれを言い換えることができますか? – ThisSuitIsBlackNot

+0

+/- 5行が近いです....私は近道のために指定できるパラメータをツールが受け入れることを望んでいます –

+0

"path"と "redirect"は同じ行に表示されていますか? – fedorqui

答えて

1

簡単なフィルタは、「フラッシュ」が付いたフィルタです。最初に行うこともお勧めです。これにより、より高価なパターンマッチングがマッチしたファイルのサブセットで行われます。このため

、ちょうど言う:

grep -RH -C 5 "text" * 

これます再帰的に(-R)パターン「テキスト」を探し、ファイル(-H)の名​​前を印刷するこの問題が発生したとき。また、周囲の5行(-C 5)を印刷します。必要に応じて変数を5に変更してください。

そして、2つのパターンを確認するためのawkを使用する時間です:

awk '/pattern1/ && /pattern2/ {print FILENAME}' file 

これはawk is quite good on multiple patterns matchingとして有用です。

我々は、ファイル名が、フォームfilename:flashなどのストリームを持っていないので、我々はgrepから結果処理するための基本的なバッシュループ持つことができます。これは、それよりも少し複雑です

while IFS=":" read -r filename data; 
do 
    awk -v f="$filename" '/path/ && /redirect/ {print f}' <<< "$data" 
done < <(grep -RH -C5 "text" *) 
+0

これでファイルが2回読み取られることになりますか?最初はgrepに、2番目はawkに? – Sobrique

+1

@Sobriqueそうではありません。それは2回のパスを行いますが、2回目のパスは "text"という単語の各インスタンスを囲む10行だけを検索します。これは、 "text"がすべての1行に現れた場合、かなり非効率的になるでしょう。したがって、明らかにそれは頻繁に現れないということです。 – ThisSuitIsBlackNot

0

をあなたが大雑把に近い言葉を探しているからです。

だから私はおそらく、少しこのようにそれに取り組むだろう:

#!/usr/bin/env perl 

use strict; 
use warnings; 

my $buffer_limit = 5; # +/- 5 

my @buffer; 

my $first_flag; 
my $second_flag; 

#iterate stdin or files specified on command line 
while (my $line = <>) { 

    #test first condition 
    if ($line =~ m/path/ and $line =~ m/redirect/) { $first_flag++; }; 
    #test second condition 
    if ($line =~ m/flash/) { $second_flag++; }; 

    #if either is true - match has been seen recently. 
    #save the line in the buffer. 
    if ($first_flag or $second_flag) { 
     push @buffer, $line 
    } 
    #if both are true, we print (and flush the buffer) 
    if ($first_flag and $second_flag) { 
     print "Match found up to line $.:\n"; 
     print @buffer; 
     @buffer =(); 
     $first_flag = 0; 
     $second_flag = 0; 
    } 
    #exceeding limit means that both matches haven't been seen in proximity. 
    if (@buffer > $buffer_limit) { 
     @buffer =(); 
     $first_flag = 0; 
     $second_flag = 0; 
    } 
} 

我々は、ローリング5ラインバッファを使用します。 1つまたは他の「マッチ」に当たったときにキャプチャを開始し、2回目のマッチに当たったらプリント/フラッシュします。そして5行を超えるとバッファを空にします。

+2

私はそれを取るステートメント修飾子が好きではない?また、 '@ buffer'に行を保存しているだけです(OPは各ファイルに合格/不合格を要求します)ので、2つのフラグを' $ buffer_limit'に設定して、ゼロ以外の再 – Borodin

1
ack -A6 -B4 'path.*redirect|redirect.*path' FILES | grep flash 

4行前またはファイル名及びflashを含む行の行番号と共にパターンpathredirectを含むファイルFILESの行の後に6行にパターンflashを含む出力ライン。

ackコマンド(またはも動作しますegrepコマンド、)がなければ、あなたが近くにありますどのように近い2つのgrepコマンド

(grep -A6 -B4 'path.*redirect' FILES ; grep -A6 -B4 'redirect.*path' FILES) | 
    grep flash