sed - 行が条件に一致すると、パターン範囲に一致する行を印刷します。

sed - 行が条件に一致すると、パターン範囲に一致する行を印刷します。

処理する必要がある複数行のログエントリの種類があります。

ログは次のとおりです。

--START--
Device=B
Data=asdfasdf
Lorem=Ipsum
--END--
--START--
Device=A
Data=asdfasdf
Lorem=Ipsum
--END--
--START--
Device=B
Data=asdfasdf
--END--
--START--
Device=A
Data=asdfasdf
--END--
--START--
Device=B
Data=asdfasdf
--END--
--START--
Device=C
Data=asdfasdf
Lorem=Ipsum
--END--

特定のパターンが一致する場合は、--START--間のすべての内容を印刷したいと思います。--END--

たとえば、

すべてのアイテムを印刷Device=A

--START--
Device=A
Data=asdfasdf
Lorem=Ipsum
--END--
--START--
Device=A
Data=asdfasdf
--END--

これまで私ができることは、次のように書くだけです。

sed -e -n '/--START--/,/--END--/p' < input

{}入力値を効果的に出力しますが、フィルタを追加しNてから条件が一致したら出力する必要があるようです。

私も完全に迷子になったような気がする。

1行が条件に一致する場合は、複数行を印刷する方法を知っていますか?

答え1

$ sed -n '/--START--/{:a;N;/--END--/!ba; /Device=A/p}' file
--START--
Device=A
Data=asdfasdf
Lorem=Ipsum
--END--
--START--
Device=A
Data=asdfasdf
--END--

(上記はGNU sedでテストされています。BSD / OSXで実行するように調整する必要があります。)

仕組み:

  • /--START--/{...}

    含まれている行に達するたびに、中--START--括弧内のコマンドが実行されます{...}

  • :a

    ラベルを定義しますa

  • N

    次の行を読み、パターンスペースに追加してください。

  • /--END--/!ba

    パターンスペースに現在のラベルが含まれていない場合は、--END--ラベルに戻りますa

  • /Device=A/p

    ここまで来るとパターン空間がで始まり--START--で終わるという意味です--END--。さらに、パターンスペースにそれが含まれている場合はDevice=A、それを印刷しpてください。

答え2

sed予約済みスペースを使用したその他のバリエーション

sed 'H              #add line to hold space
     /--START--/h   #put START into hold space (substitute holded in)
     /--END--/!d    #clean pattern space (start next line) if not END
     x              #put hold space into pattern space
     /Device=A/!d   #clean pattern space if it have not "Device=A"
    ' file

答え3

そしてsed

$ -e:1 -e'$!N;/--END--/{
  /Device=A/!d
  b
}' -eb1 <file
--START--
Device=A
Data=asdfasdf
Lorem=Ipsum
--END--
--START--
Device=A
Data=asdfasdf
--END--

--START--これにより、パターン空間とパターン空間の間のすべての行が読み取られます--END--。一致した場合は、--END--パターンスペースに含まれていないことを確認してDevice=A削除し、そうでない場合はsedパターンスペースを印刷して次のループを開始します。

そしてawk

awk '
  /--START--/ {
    getline d
    if (d ~ /Device=A/) {
      p = 1
      printf "%s\n%s\n", $0, d
      next
     }
  }
  p
  /--END--/ { p = 0 }
' <file

答え4

ここでは、文字列間の文字列をテストする方法を示すいくつかの他の良い答えがすでにあります。--START--そして--END--しかし、例の入力を考慮すると、実際に心配する必要はありません。--START--別言します。

sed -n '$!N;/^Device=A\n/,/\n--END--/P;D'

...すべてを印刷しますDevice=A\n次のエントリが発生するまで発生する最後のEwline--END--各ブロックに。大丈夫です。--START--あえて確認する必要はないようだからだ。

したがって、次のブロックの場合:

--START--
Device=A
...stuff...
--END--

...出力は次のとおりです。

Device=A
...stuff...

...しかし、このようなブロックの場合は...

--START--
Device=B
Device=A
...stuff...
--END--

...同じ結果が出力されます。

N最後の行ではなく、すべての行に追加の入力行を追加することで機能するため、パターンスペースは次のようになります。!$

^line1\nline2$

シーケンス間に発生するすべてのパターン空間について^Device=A\nそして\n--END--現在のパターンの2行の最初の行がP印刷された後にD削除され、残りの内容で次のループが始まります。次のパターン空間は次のとおりです。

^line2\nline3$

関連情報