web-dev-qa-db-ja.com

パターンに一致する各行の前にN番目の行のみを印刷します

検索パターンの前に<N>th行だけを印刷しようとしています。 grep -B<N>は、検索パターンの前にすべての<N>行を出力します。検索パターンの後に<N>th行のみを出力できるawkコード here を見ました。

awk 'c&&!--c;/pattern/{c=N}' file

これを変更して、patternに一致する各行の前に<N>th行のみを印刷する方法は?たとえば、ここに私の入力ファイルがあります

...
...
   0.50007496  0.42473932  0.01527831
   0.99997456  0.97033575  0.44364198
Direct configuration=     1
   0.16929051  0.16544726  0.16608723
   0.16984300  0.16855274  0.50171112
...
...
   0.50089841  0.42608090  0.01499159
   0.99982054  0.97154975  0.44403547
Direct configuration=     2
   0.16931296  0.16553376  0.16600890
   0.16999941  0.16847055  0.50170694  
...

検索文字列2nd lineの前にDirect configurationを返すコマンドが必要です。これをSUSE-Linuxで実行しようとしています

5
WanderingMind

行のバッファを使用する必要があります。

これを試してみてください:

awk -v N=4 -v pattern="example.*pattern" '{i=(1+(i%N));if (buffer[i]&& $0 ~ pattern) print buffer[i]; buffer[i]=$0;}' file

N値を、印刷するパターンの前のN行目に設定します。

patternvalueを検索する正規表現に設定します。

bufferN要素の配列です。それは行を格納するために使用されます。パターンが見つかるたびに、パターンの前のNth行が印刷されます。

11
Jay jargot

そのコードは前の行では機能しません。一致したパターンの前にラインを取得するには、すでに処理されたラインを何らかの方法で保存する必要があります。 awkには連想配列しかないため、awkでやりたいことを同じように簡単に行う方法は考えられないので、Perlのソリューションを次に示します。

_Perl -ne 'Push @lines,$_; print $lines[0] if /PAT/; shift(@lines) if $.>LIM;' file 
_

PATを一致させたいパターンに、LIMを行数に変更します。たとえば、fooが出現する前に5行目を出力するには、次のように実行します。

_Perl -ne 'Push @lines,$_; print $lines[0] if /foo/; shift(@lines) if $.>5;' file 
_

説明

  • _Perl -ne_:入力ファイルを1行ずつ読み取り、_-e_で指定されたスクリプトを各行に適用します。
  • _Push @lines,$__:現在の行(_$__)を配列_@lines_に追加します。
  • _print $lines[0] if /PAT/_:現在の行が目的のパターンに一致する場合、配列_@lines_(_$lines[0]_)の最初の要素を出力します。
  • shift(@lines) if $.>LIM;:_$._は現在の行番号です。それが制限より大きい場合は、配列_@lines_から最初の値を削除します。その結果、_@lines_には常に最後のLIM行があります。
8
terdon
tac file | awk 'c&&!--c;/pattern/{c=N}' | tac

しかし、これは、互いにN行以内に複数の一致がある場合の「フォワード」ユースケースと同じ省略です。

また、実行中のプロセスから入力がパイプ処理されている場合はあまり機能しませんが、入力ファイルが完全で拡張されていない場合は、これが最も簡単な方法です。

4
JigglyNaga

sedによる代替方法。

N = 1の場合:

sed '$!N; /.*\n.*pattern/P; D' FILE

N = 2の場合

sed '1N; $!N; /.*\n.*\n.*pattern/P; D' FILE

N = 2の場合、最初の行はパターンスペースの次のN-1行を読み取り、次にN;P;Dサイクルを開始します-別の行を読み取りますパターンスペースの最後の行が一致する場合は、パターンスペースの最初の行を印刷してから削除し、新しいサイクルを開始します。

欠点は[〜#〜] n [〜#〜]の異なる値に対して変更する必要があることです:

N =の場合:

sed '1{N;N}; $!N; /.*\n.*\n.*\n.*pattern/P; D' FILE

N = 4の場合:

sed '1{N;N;N}; $!N; /.*\n.*\n.*\n.*\n.*pattern/P; D' FILE

したがって、[〜#〜] n [〜#〜]の値を大きくすると、スクリプトファイルを準備してsedに渡すことができますが、すぐに煩雑になります。

4
don_crissti