質問:一致するパターンを含む行の直後に単一行を印刷したい。
私のバージョンのsed
は、次の構文を取りません(+1p
を爆破します)。
sed -n '/ABC/,+1p' infile
私はawk
が複数行処理を行う方が良いと思いますが、どうすればいいかわかりません。
Wordの「パターン」は、非常に曖昧なため使用しないでください。常に "string"または "regexp"(またはシェルの "globbing pattern")のいずれかを使用してください。
あなたが望む具体的な答えは:
awk 'f{print;f=0} /regexp/{f=1}' file
または、正規表現の後のN番目のレコードのより一般的なソリューション(下記のイディオム "c")を専門とする:
awk 'c&&!--c; /regexp/{c=1}' file
次のイディオムは、特定の正規表現を指定して一致するレコードの範囲を選択する方法を説明しています。
a)正規表現のすべてのレコードを印刷します。
awk '/regexp/{f=1}f' file
b)正規表現の後にすべてのレコードを印刷します。
awk 'f;/regexp/{f=1}' file
c)正規表現の後、N番目のレコードを印刷します。
awk 'c&&!--c;/regexp/{c=N}' file
d)正規表現の後、N番目のレコードを除くすべてのレコードを印刷します。
awk 'c&&!--c{next}/regexp/{c=N}1' file
e)正規表現の後にN個のレコードを印刷します。
awk 'c&&c--;/regexp/{c=N}' file
f)正規表現の後、Nレコードを除くすべてのレコードを印刷します。
awk 'c&&c--{next}/regexp/{c=N}1' file
g)正規表現からN個のレコードを出力します:
awk '/regexp/{c=N}c&&c--' file
変数名を「found」の「f」から「count」の「c」に変更しました。これは、変数が実際に何であるかをより適切に表現するためです。
あなたが興味を持っているのと一致するのは、行afterですよね? sedでは、次のように実現できます。
sed -n '/ABC/{n;p}' infile
あるいは、grepのAオプションを探しているかもしれません。
-A NUM, Print NUM lines of trailing context after matching lines.
たとえば、次の入力ファイルがある場合:
foo
bar
baz
bash
bongo
次を使用できます。
$ grep -A 1 "bar" file
bar
baz
$ sed -n '/bar/{n;p}' file
baz
お役に立てば幸いです。
パターンの後にすべての行を印刷する必要があったので(ok Ed、REGEX)、私はこれに決めました:
sed -n '/pattern/,$p' # prints all lines after ( and including ) the pattern
しかし、私はすべての行を印刷した後、パターンを除外したいので
sed -n '/pattern/,$p' | tail -n+2 # all lines after first occurrence of pattern
あなたの場合、最後にhead -1
を追加できると思います
sed -n '/pattern/,$p' | tail -n+2 | head -1 # prints line after pattern
awkバージョン:
awk '/regexp/ { getline; print $0; }' filetosearch
これはあなたのために働くかもしれません(GNU sed):
sed -n ':a;/regexp/{n;h;p;x;ba}' file
Seds grepのようなオプション-n
を使用し、現在の行に必要な正規表現が含まれている場合、現在の行を次の行に置き換え、その行をホールドスペース(HS)にコピーし、行を印刷し、パターンスペースを交換します(PS) HSと繰り返します。
パターンが一致する場合、次の行をパターンバッファにコピーし、リターンを削除してから終了します。副作用は印刷です。
sed '/pattern/ { N; s/.*\n//; q }; d'
実際、pattern
がcontinuous
行に一致する場合、sed -n '/pattern/{n;p}' filename
は失敗します。
$ seq 15 |sed -n '/1/{n;p}'
2
11
13
15
予想される答えは次のとおりです。
2
11
12
13
14
15
私の解決策は次のとおりです。
$ sed -n -r 'x;/_/{x;p;x};x;/pattern/!s/.*//;/pattern/s/.*/_/;h' filename
例えば:
$ seq 15 |sed -n -r 'x;/_/{x;p;x};x;/1/!s/.*//;/1/s/.*/_/;h'
2
11
12
13
14
15
説明:
x;
:入力からの各行の先頭で、x
コマンドを使用して、pattern space
とhold space
の内容を交換します。/_/{x;p;x};
:pattern space
であるhold space
が実際に_
を含む場合(これは、最後の行がindicator
と一致したかどうかを示すpattern
にすぎません)、x
を使用してcurrent line
の実際のコンテンツをpattern space
に交換し、p
を使用してcurrent line
を出力し、x
を使用してこの操作を回復します。x
:pattern space
およびhold space
の内容を復元します。/pattern/!s/.*//
:current line
がpattern
と一致しない場合、つまり、次の行を印刷しないで、s/.*//
コマンドを使用してpattern space
のすべての内容を削除します。/pattern/s/.*/_/
:current line
がpattern
と一致する場合、つまりNEXTの次の行を印刷する必要がある場合、indicator
を設定して、sed
にNEXT行を印刷するように指示する必要があるため、s/.*/_/
を使用してすべてを置換するpattern space
の内容を_
に追加します(2番目のコマンドはこれを使用して、最後の行がpattern
と一致したかどうかを判断します)。h
:hold space
をpattern space
の内容で上書きします。次に、hold space
のコンテンツは、^_$
がcurrent line
がpattern
に一致することを意味する、または^$
がcurrent line
がpattern
に一致しないことを意味します。s/.*/_/
の後、pattern space
は/pattern/
と一致できないため、s/.*//
を実行する必要があるため、5番目のステップと6番目のステップは交換できません。