sed XML 从第 x 行开始,返回下一次出现的行号

sed XML 从第 x 行开始,返回下一次出现的行号

我正在从 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

相关内容