web-dev-qa-db-ja.com

ファイル内のテキストをgrepし、テキストが含まれている段落を表示する方法は?

以下は、ファイル内のテキストです。

Pseudo name=Apple
Code=42B
state=fault

Pseudo name=Prance
Code=43B
state=good

「42B」をgrepし、上記のテキストから次のような出力を取得する必要があります。

Pseudo name=Apple
Code=42B
state=fault

grep/awk/sedを使用してこれを実現する方法についてのアイデアはありますか?

25
Jaya William

awk

awk -v RS='' '/42B/' file

RS=は、入力レコードセパレータを改行から空白行に変更します。レコードのいずれかのフィールドに/42B/が含まれている場合は、レコードを印刷します。

''(null文字列)は、空白行を表すために使用されるマジック値です POSIXによると

[〜#〜] rs [〜#〜]がnullの場合、レコードは<newline>に1つまたはそれ以上の空白行、先頭または末尾の空白行は、入力の最初または最後に空のレコードを生じさせず、<newline>は、[〜#〜] fs [〜#〜]です。

出力セパレーターは単一の改行のままであるため、出力段落は分離されません。出力段落の間に空白行があることを確認するには、出力レコード区切り文字を2つの改行に設定します。

awk -v RS='' -v ORS='\n\n' '/42B/' file
39
llua

データが常にその前後の行になるように構造化されていると想定すると、grepの-A(after)および-B(before)スイッチを使用して、一致する前の1行とその後の1行を含めるように指示できます。

$ grep -A 1 -B 1 "42B" sample.txt
Pseudo name=Apple
Code=42B
state=fault

検索語の前後に同じ数の行が必要な場合は、-C(コンテキスト)スイッチを使用できます。

$ grep -C 1 "42B" sample.txt
Pseudo name=Apple
Code=42B
state=fault

複数の行を照合する際により厳密にしたい場合は、ツール pcregrep を使用して、複数の行のパターンを照合できます。

$ pcregrep -M 'Pseudo.*\n.*42B.*\nstate.*' sample.txt
Pseudo name=Apple
Code=42B
state=fault

上記のパターンは次のように一致します。

  • -M-複数行
  • 'Pseudo.*\n.*42B.*\nstate.*'-最初の文字列がWordで始まる文字列のグループに一致します"Pseudo"行末までの任意の文字\n、文字列"42B"までの任意の文字、その後行末までの任意の文字(\n) 、その後に文字列"state"followedと任意の文字が続きます。
14
slm

おそらく同様にawkでそれを行う簡単な方法がありますが、Perlで:

cat file | Perl -ne 'BEGIN { $/="\n\n" }; print if $_ =~ /42B/;'

これは基本的に、ファイルを空白行で区切られたチャンクに分割し、正規表現に一致するチャンクのみを出力することを示しています。

4
HorsePunchKid

Unixのいくつかの種類のgrepには-p「パラグラフ」のフラグ。私は知っています AIXはあります

grep -p 42B <myfile>

あなたがそこに求めていることを正確に行います。 YMMVとGNU= grepにはこのフラグがありません。

4
Morten

末尾に空の行がない他のPerlソリューション:

Perl -00ne 'if ($_ =~ /42B/) {chomp($_); printf "%s\n",$_}' foo

% Perl -00ne 'if ($_ =~ /42B/) {chomp($_); printf "%s\n",$_}' foo
Pseudo name=Apple
Code=42B
state=fault

% cat foo
Pseudo name=Apple
Code=42B
state=fault

Pseudo name=Prance
Code=43B
state=good
2
A.B.