Java替换所有正则表达式错误

时间:2015-05-06 12:13:24

标签: java regex replaceall

我想将所有“*”转换为“。*”,而不是“\ *”

String regex01 = "\\*toto".replaceAll("[^\\\\]\\*", ".*");
assertTrue("*toto".matches(regex01));// True

String regex02 = "toto*".replaceAll("[^\\\\]\\*", ".*");
assertTrue("tototo".matches(regex02));// True

String regex03 = "*toto".replaceAll("[^\\\\]\\*", ".*");
assertTrue("tototo".matches(regex03));// Error

如果“*”是第一个出现错误的字符: java.util.regex.PatternSyntaxException: 在索引0附近悬挂元字符'*'

正确的正则表达式是什么?

3 个答案:

答案 0 :(得分:3)

这是目前唯一能够连续处理多个转义\的解决方案:

String regex = input.replaceAll("\\G((?:[^\\\\*]|\\\\[\\\\*])*)[*]", "$1.*");

如何运作

让我们打印字符串regex以查看正则表达式引擎正在解析的实际字符串:

\G((?:[^\\*]|\\[\\*])*)[*]

((?:[^\\*]|\\[\\*])*)匹配不是\*的字符序列,或转义序列\\\*。我们匹配我们不想触摸的所有字符,并将其放入捕获组中,以便我们可以将它放回去。

上面的序列之后是未转义的星号,如[*]所述。

为了确保当正则表达式与未转义的*不匹配时我们不会“跳转”,\G用于确保下一场比赛只能从头开始字符串,或最后一个匹配结束的地方。

为什么这么长的解决方案?有必要,因为 look-behind 构造来检查{{1}之前的连续\的数量是否合适Java正则表达式正式支持奇怪或甚至不正确。因此,我们需要从左到右使用字符串,并考虑转义序列,直到我们遇到未转义的*并将其替换为*

测试程序

.*

示例输出

String inputs[] = {
    "toto*",
    "\\*toto",
    "\\\\*toto",
    "*toto",
    "\\\\\\\\*toto",
    "\\\\*\\\\\\*\\*\\\\\\\\*"};

for (String input: inputs) {
    String regex = input.replaceAll("\\G((?:[^\\\\*]|\\\\[\\\\*])*)[*]", "$1.*");
    System.out.println(input);
    System.out.println(Pattern.compile(regex));
    System.out.println();
}

答案 1 :(得分:2)

你需要在这里使用负面观察:

String regex01 = input.replaceFirst("(?<!\\\\)\\*", ".*");

(?<!\\\\)是一个负面的后瞻,即如果前面没有反斜杠,则匹配*

示例:

regex01 = "\\*toto".replaceAll("(?<!\\\\)\\*", ".*");
//=> \*toto

regex01 = "*toto".replaceAll("(?<!\\\\)\\*", ".*");
//=> .*toto

答案 2 :(得分:0)

您必须在正则表达式中以*开头的字符串为例:

(^|[^\\\\])\\*

单个插入符表示'字符串的开头'('开始锚')。

修改

除了上述更正之外,replaceAll来电中的替换字符串必须为$1.*而不是.*,以免在未转义的*丢失之前匹配匹配的字符。< / p>