通常我会在之前回答过的问题中找到答案,但这次不会(或者我不理解答案并且无法修改它们以执行我希望它们执行的操作),所以我在这里问我的第一个问题。
我的输入文件看起来像
# -*- coding: utf-8 -*-
[attachment]
[browser]
[changeset]
[components]
tracopt.versioncontrol.svn.svn_fs.subversionconnector = enabled
tracopt.versioncontrol.svn.svn_prop.subversionmergepropertydiffrenderer = enabled
tracopt.versioncontrol.svn.svn_prop.subversionmergepropertyrenderer = enabled
tracopt.versioncontrol.svn.svn_prop.subversionpropertyrenderer = enabled
[header_logo]
[inherit]
file = /etc/trac/trac.ini
[logging]
我想删除所有空白部分,例如附件、浏览器、变更集、header_logo 和日志记录。我只会保留不为空的部分。输出文件应该类似于
# -*- coding: utf-8 -*-
[components]
tracopt.versioncontrol.svn.svn_fs.subversionconnector = enabled
tracopt.versioncontrol.svn.svn_prop.subversionmergepropertydiffrenderer = enabled
tracopt.versioncontrol.svn.svn_prop.subversionmergepropertyrenderer = enabled
tracopt.versioncontrol.svn.svn_prop.subversionpropertyrenderer = enabled
[inherit]
file = /etc/trac/trac.ini
这应该发生在 bash 脚本中。我想过使用 sed :寻找正则表达式\[.+\]\n(\n)+(?=\[)
,但这似乎不适用于 sed,因为我应该提前知道正则表达式将有多少行并N
相应地使用。正则表达式还应该与 EOF 而不是 Final 一起使用\[
,但如果我找到为\[
.
知道我该怎么做吗?有比 sed 更好的方法吗?
答案1
这有点混乱sed
但可能:
sed -n '
:start
/^\[/{
h
:loop
n
/^\[/b start
/^$/b loop
x;p;g
}
p'
-n
表示默认不打印任何内容。:start
只是以后 goto 的标签。我们匹配开头的行[
并启动一组 ({...}) 命令。我们将该行复制到保留空间 (h)。我们得到下一行(n)。如果它开始,[
我们有一个空部分,所以转到 (b) 再次开始。
如果该行为空(/^$/),我们将读取另一行(goto 循环)。该行不为空,因此我们将行与保留的节标题 (x) 交换,打印节标题 (p),获取当前行 (g) 并继续从命令组中打印 (p) 该行。最后一个 (p) 还打印非节标题。
答案2
我带着以下 awk
BEGIN { empty=0 ; section = "" ; }
substr($0,1,1) == "[" { section = $0 ; next ; }
NF == 0 { if ( empty++ ) print ; section = "" ; next ; }
NF > 0 { if ( section != "" ) print section ; print ; section = "" ; }
被称为与
awk -f pgm.awk infile > outfile
然而,正如 Terdon 提到的,最好使用库,这种文件格式不是那么机密,此外库会处理cr
, cr/nl
和nl
行尾。