我正在从 XML 中删除标签部分,并且需要找到结束标签来停止。
XML 示例
<SearchPattern>
<something></something>
</SearchPattern>
<OtherTag></OtherTag>
<SearchPatternHit2>
<something></something>
</SearchPatternHit2>
迭代 1 后所需的 XML 输出示例
<OtherTag></OtherTag>
<SearchPatternHit2>
<something></something>
</SearchPatternHit2>
迭代 2 后所需的 XML 输出示例
<OtherTag></OtherTag>
我当前的尝试使用 sed 来查找第一次出现的行号,如下所示:
start_line = $(grep -n "<${SEARCH_PATTERN}" ${FILE_PATH} | head -1| cut -f1 -d':')
其输出仅为行号整数。
然后我尝试使用以下方法获取结束标记的行:
finish_line = $(sed -n "${start_line},$ !d;/<\/${LEADING_TAG}>/=" ${FILE_PATH} | head -1)
我相信当存在多个搜索模式实例时,终点线的结果不正确,因此它不会获得第一个结束标记。
在示例中,该模式位于第 1 行和第 7 行。在第一遍中,start_line=1,但 finish_line 未按应有的方式返回 3。
获得这两个值后,我调用一个有效的简单 sed 语句。
sed -i "${start_line}, ${finish_line}d" ${FILE_PATH}
从每个块获取结束标记行的更好方法是什么?
答案1
编辑 XML 的正确方法是使用 XML 解析器,因为它可以处理显示格式的更改,例如添加空格或不同的行布局。我目前首选的是xmlstarlet
。
给定一个有效的 XML 文档:/tmp/xml
<?xml version="1.0"?>
<root>
<SearchPattern>
<something/>
</SearchPattern>
<OtherTag/>
<SearchPatternHit2>
<something/>
</SearchPatternHit2>
<SearchPatternHit2>
<something_else/>
</SearchPatternHit2>
</root>
您可以<searchPattern/>
非常简单地删除该部分
xmlstarlet edit -d '//SearchPattern' /tmp/xml
要删除重复元素的一次出现,请包含数组引用(从 1 开始)
xmlstarlet edit -d '//SearchPatternHit2[1]' /tmp/xml
答案2
我找到了一个简单的解决方案,有点hacky,但我无法在系统上放置其他工具,所以这是我的解决方案。
我的脚本在将每个片段放入 XML 之前和之后添加了通用注释,然后可以使用 grep 找到该注释,并使用相同的简单 sed 语句轻松删除。
新的XML
1. <!-- START MY CONFIG ADDITIONS-->
2. <SearchPattern>
2. <something></something>
3. </SearchPattern>
4. <!-- END MY CONFIG ADDITIONS--
5.
6. <OtherTag></OtherTag>
7.
8. <!-- START MY CONFIG ADDITIONS-->
9. <SearchPatternHit2>
10. <something></something>
11. </SearchPatternHit2>
12. <!-- END MY CONFIG ADDITIONS-->
新变量
start_line=$(grep -n "<!-- START MY CONFIG ADDITIONS-->" ${FILE_PATH} | head -1 | cut -f1 -d':')
finish_line=$(grep -n "<!-- END MY CONFIG ADDITIONS-->" ${FILE_PATH} | head -1 | cut -f1 -d':')
代码
count=$(grep -c "<!-- START MY CONFIG ADDITIONS-->" ${FILE_PATH})
while [ $count -gt 0 ]; do
start_line=$(grep -n "<!-- START MY CONFIG ADDITIONS-->" ${FILE_PATH} | head -1 | cut -f1 -d':')
finish_line=$(grep -n "<!-- END MY CONFIG ADDITIONS-->" ${FILE_PATH} | head -1 | cut -f1 -d':')
sed -i "${start_line}, ${finish_line}d" $FILE_PATH
((count--))
done