我的工具获得纯文本,并逐渐通过从标签中的文字替换来生成“标签”。由于存在一些复合词,唯一方式(我认为)使用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
答案 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}}。