站在网络上其他人的伟大之处(对他们的支持),我遇到了这个命令:
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 更复杂,它就会中断。