如果重复则删除与模式匹配的行

如果重复则删除与模式匹配的行

假设我有一个配置文件:

[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

通常,为了便于阅读,我会写成多行,但由于您要求一行:

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变量包含某些内容,则输出标题。然后输出当前行。

这或多或少是直译艾德·格林的回答进入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

相关内容