如何逐个转义所有正则表达式特殊字符而非一次性转义所有(使用Pattern.quote()方法)?

5
问题在于:用户面对一个文本框,可以在其中输入过滤器。这个过滤器是用来过滤未过滤数据的。用户经历了Oracle Forms洗脑,除了%外,他们不期望有其他特殊字符。我猜%在Java中更或多少代表“.*”正则表达式。
如果用户行为良好,将输入类似“CTHULH%”这样的内容,那么我可以构建一个模式:
Pattern.compile(inputText.replaceAll("%", ".*"));

但是如果用户来自Innsmouth,那么他只需轻松按几个键就可以打破我设计的密码。他会打入".+\[a-#$%^&*(",这样做是行不通的:

Pattern.compile(Pattern.quote(inputText).replaceAll("%", ".*"));

由于会在字符串开头加上\Q以及在字符串结尾加上\E,因此我的% -> .*将变得无效。

问题是:我是否需要查找Pattern代码中的每个特殊字符并自己添加"\\"进行转义,还是可以自动完成?或者我是否已经深入问题中,忽略了一些明显的解决方法?

2个回答

6
我认为这个算法对您应该有效:
  • %拆分。
  • 使用Pattern.quote单独引用每个部分。
  • 使用.*连接字符串。

谢谢!代码很整洁,但需要注意一下字符串开头和/或结尾是否有“%”。 - pafau k.

2

那么Pattern.compile(Pattern.quote(inputText).replaceAll("%", "\\E.*\\Q"));是什么意思呢?

这将会得到以下的模式:

input:   ".+\[a-#$%^&*(" 
quote:   \Q".+\[a-#$%^&*("\E 
replace: \Q".+\[a-#$\E.*\Q^&*("\E

如果百分号(%)是正则表达式的第一个或最后一个字符,你将得到一个 \Q\E (如果你只有输入的 %,那么表达式将变成 \Q\E.*\Q\E),但这仍然是一个有效的表达式。
更新:
我忘记了 replace(...)replaceAll(...) 之间的区别:前者中的替换参数是字面量,而后者中的替换参数本身是一个表达式。因此 - 正如你在评论中已经指出的那样 - 你需要调用 Pattern.compile(Pattern.quote(inputText).replaceAll("%", "\\\\E.*\\\\Q"));(引用字符串和表达式中的反斜杠)。
来自于 String#replaceAll(...) 文档:

请注意,替换字符串中的反斜杠可能会导致结果与将其视为字面替换字符串时不同。


+1 但我不确定quote方法的文档是否保证字符串始终会被\Q\E括起来(它只是说“此方法生成一个字符串,可以用于创建模式,该模式将匹配字符串s,就像它是文字模式一样。”)。虽然在实践中,我认为当前所有现有的Java实现都使用\Q...\E方法来实现这一点。 - Mark Byers
@Thomas 不好意思问个新手问题 - 这里的惯例是什么?当你更新答案时,我需要删除我的评论吗? - pafau k.
@pafauk。嗯,我不确定,但如果注释没有提供任何额外信息(我认为我们现在的注释是如此),我会将它们删除以保持帖子清晰。我将开始并删除我的先前评论。 - Thomas

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接