重複している場合、パターンに一致する行を削除する

重複している場合、パターンに一致する行を削除する

設定ファイルがあるとしましょう。

[main]
foo = bar
[option]
opt1 = opt2
opt3 = opt4
[extra]
[footer]
[tail]
print = true
[end]

[text]以下のオプションがある場合にのみタイトル()を印刷したいと思います。したがって、出力は次のようになります。

[main]
foo = bar
[option]
opt1 = opt2
opt3 = opt4
[tail]
print = true

答え1

通常、読みやすくするために複数行で書いていますが、1行を要求したので、

perl -ne '$head = $_ and next if /^\[/; $head and print $head and undef $head; print'

答え2

ポータブルsed; gnu sedではないはずです。ファイルをconfのままにします。

 sed -E 'N;/^\[.+\]\n\[.+\]$/!P;D' conf

Gnu sedがデフォルトのポータブルに設定されている場合

sed --posix -E 'N;/^\[.+\]\n\[.+\]$/!P;D' conf

答え3

$ awk '/^\[/ { head = $0; next } head != "" { print head; head = "" } { print }' file
[main]
foo = bar
[option]
opt1 = opt2
opt3 = opt4
[tail]
print = true

プログラムawkは見つかった各ヘッダーを変数に保存しhead、すぐに次の入力行に移動します。

行がいいえヘッダ行、head変数に何かが含まれている場合はヘッダを出力します。その後、現在の行を出力します。

これはほとんど文字通りの翻訳です。Ed Greenの回答入力するawk


やや直接的には次のように変換されますsed。ここでは、以下のように最新のヘッダーを維持するためにスペースが予約されています。

/^\[/ {
    h;    # store header in hold space (overwriting)
    d;    # delete pattern space, start next cycle
}

x;                   # swap with hold space
/./ { p; s///g; };   # if non-empty, print and empty
x;                   # swap with hold space

またはシングルライナーで

$ sed -e '/^\[/{ h;d; }' -e 'x; /./{ p;s///g; }' -e x file
[main]
foo = bar
[option]
opt1 = opt2
opt3 = opt4
[tail]
print = true

別の短いsedバリエーションは、ファイルの末尾に空のセクション/ヘッダーがあるという事実に依存します。

$ sed -n -e'/^\[/{ x;/\n/p;d; }' -e H file
[main]
foo = bar
[option]
opt1 = opt2
opt3 = opt4
[tail]
print = true

これにより、ヘッダーとそれに関連する他の行が予約済みスペースに保存されます。新しいヘッダーが見つかると、予約済みスペースが置き換えられ、改行が確認されます。見つかったら印刷してください。他の行は単に予約済みスペースに追加されます。

なぜならawk、これは次のとおりです

awk '/^\[/ { if (sect ~ ORS) print sect; sect = $0; next } { sect = sect ORS $0 }' file

関連情報