使用 sed 或 Perl 来注释 XML 块的正则表达式

Posted

技术标签:

【中文标题】使用 sed 或 Perl 来注释 XML 块的正则表达式【英文标题】:Regex using sed or Perl to comment XML Block 【发布时间】:2022-01-07 10:42:24 【问题描述】:

我正在尝试仅使用 sedperl -pi(我唯一可用的工具)在 openAM 内的 web.xml 中评论一个部分。

所以,我在这里复制:

  <servlet-mapping>
    <servlet-name>AgentConfigurationServlet</servlet-name>
    <url-pattern>/agentconfig/*</url-pattern>
  </servlet-mapping>
  <servlet-mapping>
    <servlet-name>VersionServlet</servlet-name>
    <url-pattern>/ccversion/*</url-pattern>
  </servlet-mapping>
  <servlet-mapping>
    <servlet-name>FSServlet</servlet-name>
    <url-pattern>/federation/*</url-pattern>
  </servlet-mapping>

但我试图只评论&lt;servlet-mapping&gt;...&lt;/servlet-mapping&gt;(但只有带有/ccversion 的评论。我尝试了所有方法,但无法使其正常工作。

我尝试了什么:

sed -e "s/(<servlet-mapping>[\r\n]+.*[\r\n]+.*\/ccversion.*[\r\n]+.*)/<\!-- \$1 -->/"

【问题讨论】:

【参考方案1】:

您应该使用支持 XML 的工具来处理 XML。你提到 Perl,有几个 XML 处理模块可用。

但是,如果您坚持,请自担风险尝试以下操作:

perl -0777 -pe 's.*\K(<servlet-mapping>\s*.*?<url-pattern>/ccversion/.*?</servlet-mapping>)<!-- $1 -->s' file.xml
-0777 以“slurp 模式”读取文件,即读取整个文件,而不是逐行处理; 最初的.*\K 用于匹配并忘记我们感兴趣的&lt;servlet-mapping&gt; 之前的所有内容; .*?需要问号(“节俭量词”)只匹配最近的&lt;url-pattern&gt;,同样第二个匹配最近的&lt;/servlet-mapping&gt;,而不是匹配到最后一个; 最后的 s 修饰符将点更改为也匹配换行符。

顺便说一句,在xsh 中,我碰巧维护了XML::LibXML 的包装,同样可以通过

open file.xml ;
for my $sm in //servlet-mapping[url-pattern="/ccversion/*"]
    xinsert comment "$sm" replace $sm ;
save :b ;    

【讨论】:

【参考方案2】:

因为有人不得不说,我需要练习 :) 下面是如何使用 libxml 身份转换:

comment.xsl

<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="/info/servlet-mapping[url-pattern[text()='/ccversion/*']]">
        <xsl:text disable-output-escaping="yes">&lt;!-- </xsl:text>
            <xsl:copy>
                <xsl:apply-templates select="@*|node()"/>
            </xsl:copy>
        <xsl:text disable-output-escaping="yes"> --&gt;</xsl:text>
    </xsl:template>
</xsl:stylesheet>

xsltproc comment.xsl input.xml

输出

<?xml version="1.0"?>
<info>
    <servlet-mapping>
        <servlet-name>AgentConfigurationServlet</servlet-name>
        <url-pattern>/agentconfig/*</url-pattern>
    </servlet-mapping>
    <!-- <servlet-mapping>
        <servlet-name>VersionServlet</servlet-name>
        <url-pattern>/ccversion/*</url-pattern>
    </servlet-mapping> -->
    <servlet-mapping>
        <servlet-name>FSServlet</servlet-name>
        <url-pattern>/federation/*</url-pattern>
    </servlet-mapping>
</info>

【讨论】:

以上是关于使用 sed 或 Perl 来注释 XML 块的正则表达式的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 sed 或 perl 删除 `<a href="file://a>`keep this text`</a>`?

perl替代sed分裂多个|

用awk/sed去掉xml中的注释

如何在两个模式之间打印线,包括或不包括(在 sed、AWK 或 Perl 中)?

如何在两个模式之间打印线,包括或不包括(在 sed、AWK 或 Perl 中)?

如何在 sed 和 awk(和 perl)中搜索和替换任意文字字符串