テキストファイルで特定のパターンを見つけて、出力から除外しますか?

テキストファイルで特定のパターンを見つけて、出力から除外しますか?

約25000行のファイルがあります。私の例の入力と希望の出力を見てください。

入力する:

zone name tommy
* pwwn xxxxxxxx
  pwwn xyzabcda
* pwwn xcvuytnm
zone name sammy
* pwwn akslapsl
* pwwn dfgsjasl
* pwwn xcvuytnm
zone name angelfalls
* pwwn xxxxxxxx
  pwwn xyzabcda
zone name Newyork
* pwwn xxxxxxxx
  pwwn xyzabcda

希望の出力:

zone name tommy
* pwwn xxxxxxxx
  pwwn xyzabcda
* pwwn xcvuytnm
zone name angelfalls
* pwwn xxxxxxxx
  pwwn xyzabcda
zone name Newyork
* pwwn xxxxxxxx
  pwwn xyzabcda

pwwnの前の各行に*を含むすべての領域を除外するように出力したいと思います。私の例では、ゾーン名sammyには3つのpwwn行すべてに*が含まれているので、ゾーン名sammyの下のすべての*行を除外しました。

Solaris 5.10、Korn Shellを使用してください。

答え1

Awk解決策:

awk '/^zone /{ 
         if (f) print r;
         r = $0; f = 0; next 
     }
     { r = r ORS $0; if (/^[^*]* pwwn/) f = 1; }
     END{ if (f) print r }' file

出力:

zone name tommy
* pwwn xxxxxxxx
  pwwn xyzabcda
* pwwn xcvuytnm
zone name angelfalls
* pwwn xxxxxxxx
  pwwn xyzabcda
zone name Newyork
* pwwn xxxxxxxx
  pwwn xyzabcda

答え2

高速Perlパイプラインで実装した方法は次のとおりです。

perl -p00e 's/\nzone/\n\nzone/g' inputfile \
| perl -n00e '$t = $_; s/^\*.*?\n//mg; print $t if /pwwn/' \
| perl -p00e 's/\n\n/\n/'

最初の行は、各レコード間に空行を追加します。 2行目は、各レコードを繰り返しながらpwwnレコードから*で始まる行をすべて削除した後、残りの行があるかどうかを確認し、あればレコードを印刷します。 3行目は、各レコードを区切る空白行を削除します。

答え3

$ awk -v RS='(^|\n)zone' '/\n[^*]/ { print "zone" $0 }' input 
zone name tommy
* pwwn xxxxxxxx
  pwwn xyzabcda
* pwwn xcvuytnm
zone name angelfalls
* pwwn xxxxxxxx
  pwwn xyzabcda
zone name Newyork
* pwwn xxxxxxxx
  pwwn xyzabcda

スクリプトawkはレコード区切り文字(RS)を入力ファイルの先頭または改行文字に設定し、その後に「zone」という単語が続きます。次に、少なくとも1つの改行文字を含み、その後に何も含まないすべての「レコード」を印刷します*

$0「zone」はすべての入力レコードから自動的に削除されるため、「zone」という単語を印刷する必要がありますawkRS

注:RSこれは改行自体ではないため、$0各入力行の末尾に改行も含まれています(上記の「ゾーン」を印刷する理由と密接に関連しています)。これは、出力の末尾に追加の空行があることを意味します。これが問題の場合、これを解決する最も簡単な方法は、sed例えば。

awk -v RS='(^|\n)zone' '/\n[^*]/ { print "zone" $0 }' input | sed '$d'

最後に、pwwnスクリプトの正規表現マッチングをからマッチング条件の重要な部分/\n[^*]/に変更します/\n[^*] pwwn/。 (サンプル入力時の出力は同じですが、より大きな実際の入力と異なる場合があります)

関連情報