2

我的工具获取纯文本,并通过从标签中的文本替换术语来逐渐生成“标签”。由于存在一些复合术语,唯一的方法(我认为)是使用 ReplaceAll regex

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

“一个正则表达式,用于替换标签之外和另一个单词之外的所有单词”

原始代码:

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

我现在只需要替换“world”(当然标签之外)而不是“underworld”或“worldwide”

预期结果

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

1 回答 1

3

我不认为正则表达式是完成这项工作的最佳工具,但如果你只是想调整和优化你现在拥有的东西,你可以使用边界这个词\b,扔掉不必要的捕获组和可选的重复说明符,并使用所有格重复:

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

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

原始模式还包含一个看起来像(x+)?. 这可能更好地表述为 simple x*。也就是说,不是?"one-or-more"的 "zero-or-one" ,而是+简单的 "zero-or-more" *

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

另请注意[^<],我们现在禁止使用[^<>]. 现在可以将重复指定为所有格,因为在这种情况下不需要回溯。

(这[…]是一个字符类。类似[aeiou]匹配任何一个小写元音。[^…]是一个否定字符类。[^aeiou]匹配除小写元音之外的任何一个。)

当然(?!…)前瞻;它断言给定的模式不能匹配。所以整体模式是这样的:

\bworld\b(?![^<>]*+>)
\_______/\__________/ NOT the case that
 "world"                      the first bracket to its right is a closing one
 surrounded by
 word boundary anchors

参考


请注意,要在 Java 字符串文字中获得反斜杠,您需要将其翻倍,因此作为 Java 字符串文字的整个模式是"\\bworld\\b(?![^<>]*+>)".

于 2010-08-13T14:10:38.773 回答