複数行パターンの一致と行削除 - sed/awk/grep

複数行パターンの一致と行削除 - sed/awk/grep

入力.txt

-------
Database alias = ABC
Node name = node01
Hostname = hostnode01
Service name = 12345
-------
Hostname    = hostnode01
Service name    = 12345
-------
Database alias  = PQR
Node name   = node01
Hostname    = hostnode01
Service name    = 12345
-------
Hostname    = hostnode01
Service name    = 12345
-------
Database alias  = XYZ ......

期待される出力

-------
Database alias  = ABC
Node name   = node01
Hostname    = hostnode01
Service name    = 12345
-------
Database alias  = PQR
Node name   = node01
Hostname    = hostnode01
Service name    = 12345
-------
Database alias  = XYZ ......

ホスト名とサービス名(重複している場合)の重複値を削除するか、その間'-------に2行がある場合は「。」間の行を削除すると言えます。

マルチマッチングのためにsedを試しましたが、希望のo / pを取得できませんでした。

sed '/-------/{$!N;/\n.*Hostname/d;}' Input.txt

答え1

牛に似た一種の栄養awk方法:

awk 'BEGIN{ 
         RS = ORS = "-------\n";
         pat = "^Hostname += ([^ ]+)\nService name += ([^ ]+)\n$";  
     }
     NR == FNR{ 
         if (match($0, pat, a)) { items[a[1], a[2]]++ } 
         next 
     }
     match($0, pat, a) && (a[1], a[2]) in items \
     && items[a[1], a[2]] > 1{ next }1' inout.txt input.txt

出力:

-------
Database alias = ABC
Node name = node01
Hostname = hostnode01
Service name = 12345
-------
Database alias  = PQR
Node name   = node01
Hostname    = hostnode01
Service name    = 12345
-------
Database alias  = XYZ ......
-------

答え2

これは操作ではありませんsed(連続した重複項目に依存してはいけません)。使用awk:

  1. レコード区切り記号を正規表現に設定します^-+$

  2. 索引がホスト名とサービス名を連結した連想配列を使用します。読み取ったレコードの場合、そのレコードがまだ存在しない場合にのみ配列に配置されます。

  3. ファイルの処理が終わったら、----区切り文字行を使用して、別の行形式で配列内のすべての要素を印刷します。

答え3

サンプルデータセットの単純さは実際のユースケースでは一般的ではないかもしれませんが、公開されたサンプルのマイナーな特性を考慮すればgrepこれだけで十分です。

$ grep --no-group-separator -A4 '^Database alias' input.txt 
Database alias = ABC
Node name = node01
Hostname = hostnode01
Service name = 12345
-------
Database alias  = PQR
Node name   = node01
Hostname    = hostnode01
Service name    = 12345
-------
Database alias  = XYZ ......

関連情報