パターンに一致する連続行と次の3行を削除します。

パターンに一致する連続行と次の3行を削除します。

次の内容を含むファイルがあります。

dn : Does not matter
 uid=321 456 678
foo=/234
bar=/456
git=/543

 uid=321 456 678
 uid=678 987 098
foo=/234
bar=/456
git=/543

dn : Does it matter
 uid=321 456 678
foo=/543
bar=/423
git=/501

uid=予想される出力が次のように連続した項目とその後の3行を削除したいと思います。

 dn : Does not matter
 uid=321 456 678
foo=/234
bar=/456
git=/543

dn : Does it matter
 uid=321 456 678
foo=/543
bar=/423
git=/501

2つのサーバーでこれを試しました。残念ながら、私が最も使用しているサーバーにはアクセスできません。そのため、2番目のサーバーでは、次のようなさまざまなバリエーションを試しましたが、目的の結果が得られませんでした。

sed '/^ uid=/N;{/\n uid= & & \n ^change type & & \n ^replace/d;}' pattern2.txt
awk '{/pat/?f++:f=0} f==2 {f--;}; 1' < pattern2.txt
sed '/^ uid=/N;{/\n uid=/D;}' pattern1.txt
awk '{/ uid=/?f++:f=0} f==2' pattern1.txt

答え1

使用sed:

$ sed -f script.sed file
dn : Does not matter
 uid=321 456 678
foo=/234
bar=/456
git=/543

dn : Does it matter
 uid=321 456 678
foo=/543
bar=/423
git=/501

...script.sedどこ

H              # Append a newline and the current line to the hold space
/^$/bout       # Empty line: branch to ':out'
$bout          # Last line: branch to ':out'
d              # Delete line, start again from the top
:out
x              # Swap in the data from the hold space
/uid.*uid/d    # Delete the data if it contains two "uid"
s/\n//         # Remove the first embedded newline
               # (implicit print)

これはsed、「予約済みスペース」(通常のバッファー)に読み込まれた行を収集し、空行または入力の終わりに遭遇すると、予約済みスペースには元のファイルの「チャンク」の1つが含まれます。これらのブロックに2つの文字列インスタンスが含まれている場合、uidそのブロックは削除され、それ以外の場合は出力されます。

答え2

私はこれを単純化できると思いますawkが、まだそうではありません。

awk '/uid=/ && p~/uid=/{c=4; next}
     !(c && c--) && NR>1{print p} {p=$0}
     END{if(c==0)print p}' ip.txt
  • デフォルトでは、awkの初期化されていない変数は、状況によっては空の文字列またはゼロになります。
  • /uid=/ && p~/uid=/現在の行と前の行に次が含まれている場合uid=
    • c=4; nextスキップされた行数c(最終ロジックのために1を追加)で初期化します。また、残りのコードはスキップしてください。
  • !(c && c--) && NR>1{print p}現在の行番号が1より大きい場合は、前の行を印刷しますc==0cより大きい場合は0減少し続けます。c==0
  • {p=$0}後で使用するために前の行を保存してください。
  • END{if(c==0)print p}次の場合は、最後の行を印刷してください。c==0

関連情報