跨多行删除 XML 元素
我的用例几乎相同,但我需要匹配 XML 元素中的开始和结束标记并完全删除它们——包括里面的任何内容。
<xmlTag whatever="parameter that holds in the tag header">
<whatever_is_inside/>
<InWhicheverFormat>
<AcrossSeveralLines/>
</InWhicheverFormat>
</xmlTag>
尽管如此,仍然sed
可以在一条线上工作。我们在这里所做的是欺骗它将后续行附加到当前行,以便我们可以编辑我们喜欢的所有行,然后重写输出(\n
是一个合法的字符,您可以输出以sed
再次划分行)。
受@beano 的答案和Unix stackExchange 中的另一个答案的启发,我构建了我的工作 sed “程序”:
sed -s --in-place=.back -e '/\(^[ ]*\)<xmlTag/{ # whenever you encounter the xmlTag
$! { # do
:begin # label to return to
N; # append next line
s/\(^[ ]*\)<\(xmlTag\)[^·]\+<\/\2>//; # Attempt substitution (elimination) of pattern
t end # if substitution succeeds, jump to :end
b begin # unconditional jump to :begin to append yet another line
:end # label to mark the end
}
}' myxmlfile.xml
一些解释:
- 我匹配
<xmlTag
而不关闭,>
因为我的 XML 元素包含参数。
- 前面
<xmlTag
是一个非常有用的正则表达式来匹配任何现有的缩进:\(^[ ]*\)
所以你以后可以用 just 输出它\1
(即使这次不需要它)。
- 在几个地方添加,
;
以便sed
理解命令(N
或s
任何一个)在那里结束,后面的字符是另一个命令。
- 我的大部分麻烦是试图找到一个匹配“介于两者之间的任何东西”的正则表达式。我终于解决了
·
(即[^·]\+
)以外的任何问题,指望在任何数据文件中都没有那个字符。我需要 scape+
因为对 GNU sed 来说是特殊的。
- 我的原始文件保留为 .back,以防万一出现问题——修改后测试仍然失败——并且版本控制很容易将其标记为批量删除。
我使用这种 sed 自动化来改进 .XML 文件,我们使用这些文件与序列化数据一起运行我们的单元和集成测试。每当我们的类发生变化(松散或增益字段)时,都必须更新数据。我用一个“find”来做到这一点,它在包含修改后的类的文件中执行 sed 自动化。我们拥有数百个 xml 数据文件。