站在网络上其他人的伟大之处(对他们的支持),我遇到了这个命令:

perl -0 -p -i -e 's|<nodeName>.*?</nodeName>|$&=~/this/?"":$&|gse' file 

它将找到一个 XML 节点(在本例中为“nodeName”),查找特定字符串(在本例中为“this”),然后删除整个节点。这很甜蜜。

使用这个命令,一个看起来像这样的文件:

<nodeName> 
    <subNode>those</subNode> 
</nodeName> 
<nodeName> 
    <subNode>this</subNode> 
</nodeName> 
<nodeName> 
    <subNode>that</subNode> 
</nodeName> 
<nodeName> 
    <subNode>these</subNode> 
</nodeName> 

出来的效果是这样的:

<nodeName> 
    <subNode>those</subNode> 
</nodeName> 
<nodeName> 
    <subNode>that</subNode> 
</nodeName> 
<nodeName> 
    <subNode>these</subNode> 
</nodeName> 

但是,我的需求是让它查找“this”或“that”,如果找到其中一个,则删除整个节点。因此,为此,我正在使用此命令:

perl -0 -p -i -e 's|<nodeName>.*?</nodeName>|$&=~/this/?"":$&|gse' file;perl -0 -p -i -e 's|<nodeName>.*?</nodeName>|$&=~/that/?"":$&|gse' file 

这基本上是“运行命令两次以查找 2 个不同的东西,但执行相同的操作”。我的问题是,原始的 perl 命令可以简化为在一个命令中查找“this”或“that”吗?

我已经试过了:

perl -0 -p -i -e 's|<nodeName>.*?</nodeName>|$&=~/(this|that)/?"":$&|gse' file 

但我对 perl 有点陌生。我认为这会像这样工作:

s/(dog|cat)s are (invited|welcome)/$1s are not $2/; 

但事实并非如此。我不确定我希望完成的事情是否有可能实现。所以最后,我确实有点漫不经心。重申一下问题:是否可以简化原始 perl 命令以在一个命令中查找“this”或“that”?

提前谢谢你。

注意:我在没有安装 xmlstarlet 的服务器上工作,而且我没有安装它的授权。

请您参考如下方法:

由于您的外部正则表达式使用管道 | 作为分隔符,因此当您在内部正则表达式中使用管道作为 or 时,您将打破模式。

perl -0 -p -i -e 's{<nodeName>.*?</nodeName>}{$&=~/(?:this|that)/?"":$&}gse' file 

这样它应该可以工作。我已将管道替换为 {}。我还添加了一个非捕获组,因为没有理由保持 this|that 可用。

当然你也可以只转义内部的|,但上面的解决方案更清晰。

perl -0 -p -i -e 's|<nodeName>.*?</nodeName>|$&=~/(this\|that)/?"":$&|gse' file 

另请注意,它可能适用于每行一个标记的文件,但如果您的 XML 更复杂,它就会中断。


评论关闭
IT序号网

微信公众号号:IT虾米 (左侧二维码扫一扫)欢迎添加!