删除文件中的多行

删除文件中的多行

通常我会在之前回答过的问题中找到答案,但这次不会(或者我不理解答案并且无法修改它们以执行我希望它们执行的操作),所以我在这里问我的第一个问题。

我的输入文件看起来像

# -*- 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/nlnl行尾。

相关内容