如何优化这个正则表达式?

时间:2010-08-13 14:06:27

标签: java regex string replaceall

我的工具获得纯文本,并逐渐通过从标签中的文字替换来生成“标签”。由于存在一些复合词,唯一方式(我认为)使用ReplaceAll 正则表达式

感谢stackoverflow的朋友,在我的上一个问题中,我的应用程序得到了很好的正则表达式,但经过测试后,出现了新的需求:

  

“正则表达式替换所有单词OUTSIDE标签和其他单词之外”

原始代码:

String str = "world worldwide <a href=\"world\">my world</world>underworld world";
str = str.replaceAll("\\bworld\\b(?![^<>]*+>)", "repl");
System.out.println(str);

我现在需要只替换“世界”(在标记之外)和 NOT “黑社会”或“全球”

预期结果

repl worldwide <a href="world">my world</world>underworld repl

1 个答案:

答案 0 :(得分:3)

我不认为正则表达式是这项工作的最佳工具,但如果您只想调整和优化现在的工具,可以使用单词boundary \b,扔掉不必要的捕获组和可选的重复说明符,并使用占有重复:

\bworld\b(?![^<>]*+>)

\bworld\b将确保"world"被零宽度字边界锚定所包围。这样可以防止它与"world""underworld"中的"worldwide"匹配。请注意,单词边界定义可能不是您想要的,例如\bworld\b"world"中的"a_world_domination"不匹配。

原始模式还包含一个看起来像(x+)?的子模式。这可能更好地表达为x*。也就是说,而不是“一个或多个”?的“零或一”+,而只是“零或多”*

捕获组(…)在功能上是不需要的,并且看起来您不需要捕获替换中的任何替换,因此摆脱它可以提高性能(当您需要分组方面时,但不是捕获方面,您可以改为使用非捕获组(?:…)

另请注意,我们现在禁止使用[^<]代替[^<>]而不是[…]。现在重复可以被指定为占有性,因为在这种情况下不需要回溯。

[aeiou]character class[^…]之类的内容与任何小写元音中的一个匹配。[^aeiou]否定的字符class。(?!…)匹配除了小写元音之外的任何内容。)

当然\bworld\b(?![^<>]*+>) \_______/\__________/ NOT the case that "world" the first bracket to its right is a closing one surrounded by word boundary anchors 否定前瞻;它断言给定的模式可以 NOT 匹配。所以整体模式如下:

"\\bworld\\b(?![^<>]*+>)"

参考


请注意,要在Java字符串文字中获得反斜杠,您需要将其加倍,因此作为Java字符串文字的整个模式为{{1}}。