Unix sed 输出出现两次替换模式

Unix sed 输出出现两次替换模式

我有一个 XML 文件logback-spring.xml

现在,我想将字符串替换DEBUGTRACE,无论ref="logstash"出现在哪里仅在下一行

输入文件如下所示:

  <logger name="com.abcd.tdi" level="DEBUG" additivity="false">
        <appender-ref ref="logstash"/>
        <appender-ref ref="Async-Appender"/>
    </logger>

  <springProfile name="dev">
        <logger name="com.abcd.tdi" level="DEBUG" additivity="false">
            <appender-ref ref="logstash"/>
        </logger>
  <springProfile name="dev">
        <logger name="com.abcd.tdi" level="DEBUG" additivity="false">
            <appender-ref ref="CONSOLE"/>
        </logger>

使用命令时sed我得到输出两次在替换中。

我使用了以下sed命令:

sed -n -e '/ref="logstash"/!h' -e '/ref="logstash"/{H;x;s/DEBUG/TRACE/}; p; ' logback-spring.xml

答案1

给定一个格式良好的 XML 文档,如下所示(根据您的示例进行修改):

<?xml version="1.0"?>
<root>
  <springProfile name="dev">
    <logger name="com.abcd.tdi" level="DEBUG" additivity="false">
      <appender-ref ref="logstash"/>
      <appender-ref ref="Async-Appender"/>
    </logger>
  </springProfile>
  <springProfile name="dev">
    <logger name="com.abcd.tdi" level="DEBUG" additivity="false">
      <appender-ref ref="logstash"/>
    </logger>
  </springProfile>
  <springProfile name="dev">
    <logger name="com.abcd.tdi" level="DEBUG" additivity="false">
      <appender-ref ref="CONSOLE"/>
    </logger>
  </springProfile>
</root>

您可以使用xmlstarlet更改其子节点具有属性的每个节点level设置为 的所有属性DEBUG,如下所示:TRACEloggerappender-refreflogstash

$ xmlstarlet ed -u '//logger[appender-ref/@ref = "logstash"]/@level[. = "DEBUG"]' -v 'TRACE' file.xml
<?xml version="1.0"?>
<root>
  <springProfile name="dev">
    <logger name="com.abcd.tdi" level="TRACE" additivity="false">
      <appender-ref ref="logstash"/>
      <appender-ref ref="Async-Appender"/>
    </logger>
  </springProfile>
  <springProfile name="dev">
    <logger name="com.abcd.tdi" level="TRACE" additivity="false">
      <appender-ref ref="logstash"/>
    </logger>
  </springProfile>
  <springProfile name="dev">
    <logger name="com.abcd.tdi" level="DEBUG" additivity="false">
      <appender-ref ref="CONSOLE"/>
    </logger>
  </springProfile>
</root>

XPath 查询类似于choroba正在使用什么也可以工作:

xmlstarlet ed -u '//logger[@level = "DEBUG"][appender-ref/@ref = "logstash"]/@level' -v 'TRACE' file.xml

答案2

使用 XML 时使用可识别 XML 的工具。例如,在xsh,一个包装器XML::LibXML,你可以通过以下方式实现结果

open logback-spring.xml ;
for //logger[@level='DEBUG'][appender-ref/@ref='logstash']
    set @level 'TRACE' ;
save :b ;

如果您的 XML 包含名称空间声明,则代码会稍微复杂一些。

相关内容