1

次のようなテキスト ストリームを取得しました。

whatever => foo,
arg => 'some text
   over multiple lines
   sometimes',
bytes => 123,
...

私が興味を持っているのは、 と の間のテキストarg =>ですbytes =>。だから私はブロックを除外しました

cat mystream | awk '/arg =>/,/bytes =>/'

これは正常に動作します。しかし、テキストのどこかに単語が 1 つある場合は、ブロック全体をスキップしたいと考えています。grep -vラインだけでなく、ブロック全体のようなものです。何か案は?ありがとう。

これはawkに限定されないことに注意してください。それは私の頭に浮かんだことです。他のツールでも構いません。

4

3 に答える 3

6

/pat1/,/pat2/ の範囲を使用することは、通常は良い考えのように思えますが、条件を追加するか、何か他のことを行う必要があるとすぐに、うまくいきません。IMHO、次のようなフラグを使用する方がよいでしょう:

awk '/arg =>/{f=1} f; /bytes =>/{f=0}' file

これは、完全に書き直すことなく拡張できるためです。この場合、範囲内にいるとき (つまり、"f" が設定されているとき) にレコードを作成し、必要に応じて範囲の終わりに出力します。これは常にそれを印刷します:

awk '/arg =>/{rec=""; f=1} f{rec = rec $0 ORS} /bytes =>/{ if (f) printf "%s",rec; f=0}' file

これは、レコードに「whatever」というテキストが表示される場合にのみ印刷されます。

awk '/arg =>/{rec=""; f=1} f{rec = rec $0 ORS} /bytes =>/{ if (f && (rec ~ "whatever")) printf "%s",rec; f=0}' file

これは、テキスト「whatever」がレコードに表示されない場合にのみ表示されます。

awk '/arg =>/{rec=""; f=1} f{rec = rec $0 ORS} /bytes =>/{ if (f && (rec !~ "whatever")) printf "%s",rec; f=0}' file

これは、以下のコメントからのスクリプトです(わずかに再フォーマットされています)

<tcpdump> |
awk '
   /arg =>/ {rec=""; f=1}
   f {rec = rec $0 ORS}
   /bytes =>/ {
      if (rec !~ /menuStructure|session/)
         printf "%s",rec
      f=0
   }
' | sed "s/.*bytes =>.*/\n----------\n/g" | sed "s/arg => //g"

それに基づいて、このスクリプトはあなたがやろうとしていることを行うと思います:

<tcpdump> |
awk '
   /bytes =>/ {
      if (f && (rec !~ /menuStructure|session/))
         print rec "----------"
      f=0
   }
   f {rec = rec $0 ORS}
   sub(/arg =>/,"") {rec=$0; f=1}
'
于 2012-11-27T13:57:58.687 に答える
1
awk '/arg =>/,/bytes =>/ {s=s?s:NR;if($0~/some/)exit; a[NR]=$0;e=NR;}END{for(i=s;i<=e;i++)print a[i]}' file

ブロックに「some」が含まれている場合、上記のワンライナーは(例に基づいて)何も出力しません。

于 2012-11-27T13:27:55.143 に答える
1

GNU awk でできる 1 つの方法を次に示します。

m1='arg =>'
m2='bytes =>'
pattern='some'
awk -v RS="$m1|$m2" -v start="$m1" -v end="$m2" -v pattern="$pattern" \
  'RT == end && $0 !~ pattern { print start $0 end }' < mystream

つまり、開始マーカーと終了マーカーでストリームを分割し、終了マーカーが見つかりブロックに含まれていない場合は$pattern、それを出力します。

m1m2およびpatternはすべて正規表現であるため、必要に応じて微調整できることに注意してください。m1入力ブロックに または のいずれかが含まれている場合、これは機能しないことにも注意してくださいm2。以下の Ed のメモも参照してください。

于 2012-11-27T13:57:56.700 に答える