我想将所有“*”转换为“。*”,而不是“\ *”
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附近悬挂元字符'*'
正确的正则表达式是什么?
答案 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>