シェルスクリプト: 特定の行からパターンに一致する連続する 2 行を削除したい

シェルスクリプト: 特定の行からパターンに一致する連続する 2 行を削除したい

ファイルの特定の行から、パターンに一致する特定の連続する 2 行を削除したい。

たとえば、ファイルの内容は以下のようになります。

Line1: a
Line2: b
Line3: c
Line4: Name: 123
Line5:  xyz
Line6: Name: 456
Line7:  abc

4 行目から始まる行のうち、「Name:」で始まる 1 行目のパターンに一致し、空白で始まる 2 行目のパターンに一致する行を見つけて、連続する 2 行を削除します。

sedシェルまたは他の何かを使用してこれを効率的に実行する方法はありますか?

もう少し明確にするために、MANIFEST.MF から署名/チェックサム情報を削除します。

サンプル MANIFEST.MF は以下のとおりです。以下のマニフェスト ファイルから、エントリ「Name:」を削除します。ここで、「Name:」エントリは 1 行または 2 行 (またはそれ以上) にすることができます。

当初の私の解決策は、最初の「Name:」エントリとそれに続く「SHA-256-Digest:」エントリを見つけて、ファイルの最後まで削除するというものでした。残念ながら、この解決策には、途中で必要なエントリが 1 つ削除されてしまうという問題があります。たとえば、「NetBeans-Simply-Convertible:」も削除されます。

そこで、1 行に存在する場合、または 2 行以上にまたがるエントリが存在する場合は、「Name:」エントリを削除したいと思います。ただし、「Name:」エントリを削除するときに、「NetBeans-Simply-Convertible:」などのエントリが失われないようにする必要があります。

すでに私は以下のコマンドで「SHA-256-Digest:」エントリを削除しています。sed -i "/^\SHA-256-Digest: /d" $manifest_file


Manifest-Version: 1.0
Version-Info: ....

Name: com/abc/xyz/pqr/client/relationship/message/notifier/Relati
 onshipUpdateNotifierFactory.class
SHA-256-Digest: cSSyk6Y2L2F9N6FPtswUkxjF2kelMkGe4bFprcQ+3uY=

Name: com/abc/xyz/pqr/client/relationship/ui/BaseRelationshipView
 $5.class
SHA-256-Digest: w9HgRjDuP024U4CyxeKPYFe6rzuzxZF3b+9LVG36XP8=

Name: com/abc/xyz/pqr/client/impl/MofRelationshipAgentImpl.class
SHA-256-Digest: GwIBIU+UdPtjyRhayAVM90Eo+SwCT/kP65dI59adEnM=

Name: com/abc/xyz/pqr/client/settings/ConvertibleProperties.class
NetBeans-Simply-Convertible: {com/abc/xyz/pqr/client/settings}Con
 vertibleProperties
SHA-256-Digest: 5FszAtfpPXcLx/6FBWbfeg6E4fwFMRozV+Q+3rReATc= ...

期待される出力:

Manifest-Version: 1.0
Version-Info: ....


NetBeans-Simply-Convertible: {com/abc/xyz/pqr/client/settings}Con
 vertibleProperties

...

答え1

awkアプローチ:

次の入力ファイルがあるとしますfile.txt(各行にLine<number>:最初のフィールドが含まれていることを考慮)。

Line1: a
Line2: b
Line3: c
Line4: Name: 123
Line5:  xyz
Line6: Name: 456
Line7:  abc
Line8: Name: 111
Line9: www
Line10: Num: 222
Line11:  abc
Line12: Name: 333
Line13:  ccc

awk '{ if ($2 == "Name:") { 
           if ((getline l) > 0){ 
               if (l ~ /^\S+  \S+/) { next } else { print $0 RS l }               
           }
       } else { print } 
}' file.txt

出力:

Line1: a
Line2: b
Line3: c
Line8: Name: 111
Line9: www
Line10: Num: 222
Line11:  abc

'getline var'- awkの入力から次のレコードを変数に読み込むvar

取得ラインコマンドは、レコードが見つかった場合は 1 を返し、ファイルの末尾に達した場合は 0 を返します。

答え2

質問の内容が明確でないことがわかります。1つの回答では4行(一致する2行とそれに続く2行)が削除されます。もう1つの回答ではすべてが削除されます。しかし一致する行...

あなたが望んでいることを理解して、それを追加します。一致する行Name: 123とそれに続く行の 2 行を削除します。私はこれを実行しますsed:

sed -e '/Name: 123/{N;d}' filename

答え3

使用方法ed:

$ printf '%s\n' 'g/^ / s///\' '-,.j' 'g/^Name: /d' 'g/SHA-256-Digest: /d' '4,$g/^$/d' ,p Q | ed -s file
Manifest-Version: 1.0
Version-Info: ....

NetBeans-Simply-Convertible: {com/abc/xyz/pqr/client/settings}ConvertibleProperties

これにより、次の編集スクリプトが入力ファイルに適用されます。

g/^ / s///\
-,.j
g/^Name: /d
g/SHA-256-Digest: /d
4,$g/^$/d
,p
Q

これは 6 つの個別のコマンドで構成されています。

  1. 2 つのコマンドはs///-,. jスペース文字で始まるすべての行に適用されます。コマンド内の空の正規表現は、前のコマンドのs表現(正規表現に一致する行に 1 つ以上のコマンドを適用するために使用される) を再利用するため、コマンドは、空白文字で始まる行の最初の空白を削除します。次に、コマンドは変更された行を前の行と結合します。これにより、入力データ内の行の折り返しが効果的に解除されます。^gsj

  2. コマンドはdで始まるすべての行に適用されName:、これらが削除されます。

  3. 同様に、 で始まる行もSHA-256-Digest:削除されます。

  4. 4行目以降の空行は削除されます。

  5. 結果を表示するために、完全なバッファを標準出力に出力します。

  6. Qエディターを無条件に終了します (wq変更を元のファイルに書き戻すために使用できます)。

答え4

sed -e '
   4,$!d;      # skip non-relevant portion
   /Name:/N;   # grab the line coming after Name:
   /\n.* /d;   # what we were after is not this
   P;D
' yourfile

関連情報