2013-07-28 30 views
39

一致するパターンを含む行の直後に1行を出力したいとします。 (。+1pに出て、それ爆弾)sedの私のバージョンでは、簡単な解決策のように思われ、次の構文になりません。私はawkは複数行の処理を行う方が良いでしょう仮定sedまたはawkで一致するパターンに続く行を印刷する

sed -n '/ABC/,+1p' infile 

が、私はどのように確認していませんそれをするために。

+1

http://sed.sourceforge.net/sed1line.txt – devnull

答えて

27

の後に行番号があなたの興味をそそるのですか? SEDでは、それはそうのように達成することができる:

sed -n '/ABC/{n;p}' infile 

また、グレップのオプションは、あなたが探しているものかもしれません。

foo 
bar 
baz 
bash 
bongo 

あなたは以下のように使用できます:

$ grep -A 1 "bar" file 
bar 
baz 
$ sed -n '/bar/{n;p}' file 
baz 

希望に役立ちます以下の入力ファイルを指定した例

-A NUM, Print NUM lines of trailing context after matching lines. 

、。

+0

注: '{n; p}'はGNU sedではサポートされているようですが、BSD sedではサポートされていないようです。 (私はawkが必要なときに私はperlを使います) – Mars

+4

修正:BSDで成功しました。 ';': 'sed -n/bar/{n; p;}'を追加してsedを実行します。 GNU sedでも動作します。 – Mars

+0

_original_ sedを使うと、 '{'と '}'が文字コマンドとまったく同じように解析されたので 'sed -n '/ bar/{; n; p;}''と書く必要があります。 – zwol

2

awkのバージョン:

awk '/regexp/ { getline; print $0; }' filetosearch 
+1

ありがとう!私はgrepの-Aオプションを忘れていました。 +1パラメータで完全に動作します(一致したパターンの行は印刷されません)。 – user1537723

+1

これは、あまり期待していないときには不可解な方法で失敗し、将来的には強化するのが難しいでしょう。 'getline'を使うことを決める前に、準備が整っていることと、http://awk.info/?tip/getlineを完全に理解していることを確認してください。 –

+0

http://awk.freeshell.org/AllAboutGetline –

98

、それは非常に曖昧であるとして、単語 "パターン" を使用しないでください。あなたが本当に意味するところでは、常に "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)の印刷、いくつかの正規表現の後のすべてのレコード:いくつかの後のN番目のレコードを除いてすべてのレコードを印刷

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

D):

awk 'f;/regexp/{f=1}' file 

c)は、いくつかの正規表現の後に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 

グラム)いくつかの正規表現からNレコードを印刷する:

awk '/regexp/{c=N}c&&c--' file 

私はから変数名を変更しました"f"は "found"を "c"に、 "count"は として適切です。変数が実際にどのようなものかをより表現しています。

+2

素晴らしい@EdMorton –

+2

あなたは '' c &&! - c''が何をしているのか説明できますか?ありがとう! – zack

+1

cが0でない場合は、それをデクリメントしてゼロになったかどうかをテストします。したがって、ある正の数で開始された場合、その数からゼロまでカウントダウンした後に関連するアクションが実行されます。 "if c is non zero"の部分は、cが負の数にとどまっていないことを確認するためのガードです。入力ファイルが大量の場合は、再び正の値に折り返される可能性があります。 –

0

パターンが一致した場合は、次の行をパターンバッファにコピーし、リターンを削除してから、終了側の効果を印刷します。

sed '/pattern/ { N; s/.*\n//; q }; d' 
+1

'q'は決してGNU拡張ではありません。これは標準の 'sed'コマンドです。 – tripleee

+0

Yup * tripleee "... UR right ... –

3

私はパターン(OKエド、REGEX)後のすべての行を印刷するために必要なので、私はこの1つに落ち着い:

sed -n '/pattern/,$p' # prints all lines after (and including) the pattern 

しかし、私はAFTERすべての行を印刷する(そして除外したかったので、パターン)

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 
+0

2番目のケースにsed厳密な方法があります:' sed '0、/ regex/d'' – tlwhitec

1

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 

は説明:

  1. x;が:入力からの各ラインの先頭で、pattern space & hold spaceの内容を交換するxコマンドを使用します。
  2. /_/{x;p;x};:実際hold spaceあるpattern space、あれば、印刷にpを使用し、pattern spacecurrent lineの実際の内容を交換するxを使用し、(これが最後の行がpatternかと一致したかどうかを示すだけindicatorある)_が含まcurrent line、およびxを使用してこの操作を回復します。
  3. xpattern spacehold spaceの内容を復元します。
  4. /pattern/!s/.*//current lineは、我々はpattern space内のすべての内容を削除するs/.*//コマンドを使用し、その後、次の次の行を印刷しないでくださいを意味し、patternと一致しない場合。
  5. /pattern/s/.*/_/は:current lineは、我々は次の次の行を印刷する必要がありますを意味し、patternに一致する場合、我々は次の行を印刷するsedを伝えるためにindicatorを設定し、その_(第2にpattern space内のすべての内容を置換するs/.*/_/を使用する必要がありますコマンドは最後の行がpatternと一致するかどうかを判断するためにそれを使用します)。
  6. hhold spaceの内容をpattern spaceに上書きします。 hold spaceの内容が^_$であることは、pattern、または^$と一致し、current linepatternと一致しないことを意味します。
  7. s/.*/_/の後にpattern space/pattern/と一致しないので、第5ステップと第6ステップは交換できませんので、s/.*//を実行する必要があります。
+0

ありがとう、++ ve – RavinderSingh13

0

これはあなたのために働くかもしれない(GNUのSED):

sed -n ':a;/regexp/{n;h;p;x;ba}' file 

使用SEDSのgrepのようなオプション-nと、現在の行が必要な正規表現は、次のと現在の行を置き換え、その行をコピー含まれている場合ホールドスペース(HS)に移動し、ラインを印刷し、HSのパターンスペース(PS)を交換して繰り返します。

関連する問題