Perl脚本(慢慢地运行)一分钟来替换以下正则表达式:
$str = '<![CDATA[$..$]]>;
我在CDATA中有一个包含<![CDATA[$..$]]>
(不少于1000次出现)latex / tex编码的文件。因此,我需要将其更改为注释标记和处理指令,如<!--<![CDATA[--><?processingInstruction $..$?><!--]]>-->
。
$SqrBrLoopMany = qw/((?:[^\[\]]*(?:{(?:[^\[\]]*(?:{[^\[\]]*})*[^\[\]]*)*})*[^\[\]]*)*)/; # This is for using `\[ <whatever> \]` Square bracket.
$str=~s/(\<\!\[CDATA\[)$SqrBrLoopMany(\]\]>)/<\!\-\-$1\-\-><\?processingInstruction $2\?><\!\-\-$3\-\->/sg;
我正在做的上述正则表达式,但脚本需要一分钟来替换输出。
输出应为:
<!--<![CDATA[--><?processingInstruction $..$?><!--]]>-->
如果有人帮助解决这个问题,我们将不胜感激。
答案 0 :(得分:1)
最简单:
s/<!\[CDATA\[(.*?)]]>/<!--<![CDATA[--><?processingInstruction $1?><!--]]>-->/sg
CDATA不能包含任何嵌套结构,因此模式只会查找起始<![CDATA[
和最接近的结尾]]>
,并匹配其间的所有内容。
模式运行缓慢的原因是因为您在大括号[^\[\]]
之间匹配非括号({ ... }
)。如果CDATA部分包含不属于结尾[
的{{1}}或]
,则会失败并尝试依次回溯每个]]>
,从而导致quintic (O(x 5 ))执行时间。
如果需要平衡方括号以使其匹配,则可以执行
[^\[\]]*
s/<!\[CDATA\[(([^][]|\[(?2)*?])*?)]]>/<!--<![CDATA[--><?processingInstruction $1?><!--]]>-->/sg
将再次递归匹配第二个子模式/捕获组。这应该适用于基于Perl和PCRE的正则表达式引擎。
答案 1 :(得分:0)
感谢Markus Jarderot给出了解决方法/答案:
$str=~s/(\<\!\[CDATA\[)([^\]\]>]*)(\]\]>)/<\!\-\-$1\-\-><\?xmltex $2\?><\!\-\-$3\-\->/sg;
<!\[CDATA\[(.*?)]]> Instead of <!\[CDATA\[([^\]\]>]*)]]>