转义正则表达式字符串中的每个文字而不是引用整个字符串

Escape each literal in regex string instead of quote the entire string

答案 here 建议使用 Pattern.quote 以转义特殊的正则表达式字符。

Pattern.quote 的问题是它转义了整个字符串,而不是每个特殊字符。

这是我的情况:
我从用户那里收到一个字符串,需要在文档中搜索它。 由于用户无法传递换行符(这是第 3 方 API 我无权访问的错误),我决定将任何空白序列视为“\s+”并使用正则表达式来搜索文档.这样用户就可以发送一个简单的空格而不是换行符。

例如,如果文档是:

The \s metacharacter is used to find a whitespace character.

A whitespace character can be:

  • A space character
  • A tab character
  • A carriage return character
  • A new line character
  • A vertical tab character
  • A form feed character

  • 然后接收到的字符串

    String receivedStr = "The \s metacharacter is used to find a whitespace character. A whitespace character can be:";
    

    应该在文档中找到。

    为此,我想引用字符串,然后用字符串“\s+”替换任何空白序列。
    使用以下代码:

    receivedStr = Pattern.quote(receivedStr).replaceAll("\s+", "\\s+");
    

    生成正则表达式:

    \QThe\s+\s\s+metacharacter\s+is\s+used\s+to\s+find\s+a\s+whitespace\s+character.\s+A\s+whitespace\s+character\s+can\s+be:\E

    那当然会忽略我添加的 "\s+" 而不是预期的:

    The\s+\s\s+metacharacter\s+is\s+used\s+to\s+find\s+a\s+whitespace\s+character.\s+A\s+whitespace\s+character\s+can\s+be:

    只转义“\s”字面量而不是整个字符串。

    是否有 Pattern.quote 的替代方法来转义单个文字而不是整个字符串?

    我建议这样:

    String re = Stream.of(input.split("\s+"))
                      .map(Pattern::quote)
                      .collect(Collectors.joining("\s+"));
    

    这可以确保所有内容都被引用(包括那些否则会被解释为环视并可能导致匹配查找呈指数级增长的内容),并且任何用户输入的空格最终都不会被引用 \s+.

    示例输入:

    Lorem \b ipsum \s dolor (sit) amet.
    

    输出:

    \QLorem\E\s+\Q\b\E\s+\Qipsum\E\s+\Q\s\E\s+\Qdolor\E\s+\Q(sit)\E\s+\Qamet.\E