这是文件(命名为sample.xml):
<?xml version="1.0" encoding="UTF-8"?>
<configs>
<blah1 value="ma">
<tag3>100MB</tag3>
</blah1>
<blah1 value="ba">
<tag3>20MB</tag3>
</blah1>
<blah2 value="*" version="1.0" result="true">
<blah1 value="xyz">
<blah1 value="uvw" result="true">
<tag>4</tag>
</blah1>
</blah1>
</blah2>
<!-- This is tag with def value -->
<blah2 value="*" version="2.0" result="true">
<blah1 value="abc">
<blah1 value="def" result="true">
<tag2>on</tag2>
</blah1>
</blah1>
</blah2>
</configs>
使用value="def"
查找字符串时,请从<blah2> to </blah2>
标记开始删除整个块
我不熟悉sed
保持模式,但是我从Google那里得到的东西非常接近
sed -n '/<blah2.*>/,/<\/blah2>/{
H
/<\/blah2>/ {
s/.*//;x
/def/d
p
}
}' sample.xml
预期结果:
<?xml version="1.0" encoding="UTF-8"?>
<configs>
<blah1 value="ma">
<tag3>100MB</tag3>
</blah1>
<blah1 value="ba">
<tag3>20MB</tag3>
</blah1>
<blah2 value="*" version="1.0" result="true">
<blah1 value="xyz">
<blah1 value="uvw" result="true">
<tag>4</tag>
</blah1>
</blah1>
</blah2>
</configs>
实际结果(带有上述无效的sed):
<blah2 value="*" version="1.0" result="true">
<blah1 value="xyz">
<blah1 value="uvw" result="true">
<tag>4</tag>
</blah1>
</blah1>
</blah2>
答案 0 :(得分:3)
使用xmlstarlet删除第二个标签blah2
:
xmlstarlet edit --delete '//configs[blah2[2]/blah1/blah1[@value="def"]]/blah2[2]' file.xml
输出:
<?xml version="1.0" encoding="UTF-8"?>
<configs>
<blah1 value="ma">
<tag3>100MB</tag3>
</blah1>
<blah1 value="ba">
<tag3>20MB</tag3>
</blah1>
<blah2 value="*" version="1.0" result="true">
<blah1 value="xyz">
<blah1 value="uvw" result="true">
<tag>4</tag>
</blah1>
</blah1>
</blah2>
</configs>
如果要就地编辑文件,请添加选项-L。
使用过的XPath的解释:
//configs[blah2[2]/blah1/blah1[@value="def"]]/blah2[2]
|---A---| |-------------B------------------| |---C---|
A和B:您要查找的属性的路径
A和C:要删除的标签的路径
答案 1 :(得分:1)
这可能对您有用(GNU sed):
sed '/<blah2.*>/{:a;N;/<\/blah2.*>/!ba;/value="def"/d}' file
如果一行包含<blah2.*>
,请收集所有行,直到一行包含<\/blah2.*>
,然后测试这些行中的字符串value="def"
,如果找到,则删除这些行。
答案 2 :(得分:0)
由于您对sed解决方案感到满意,鉴于您发布的示例输入/输出,这是一个更好的选择(更清晰,更便携等):
$ awk -v RS= -v ORS='\n\n' '!/value="def"/' file
<?xml version="1.0" encoding="UTF-8"?>
<configs>
<blah1 value="ma">
<tag3>100MB</tag3>
</blah1>
<blah1 value="ba">
<tag3>20MB</tag3>
</blah1>
<blah2 value="*" version="1.0" result="true">
<blah1 value="xyz">
<blah1 value="uvw" result="true">
<tag>4</tag>
</blah1>
</blah1>
</blah2>
</configs>
如果这不是您所需要的,那么有什么更好的awk替代方案来满足您的需要,因为sed仅适合对单个字符串执行s / old / new。