假设我有一个配置文件:
[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