用这种模式替换并不能像我预期的那样工作,有什么问题吗?

Replacing with this pattern doesn't work as I would expect it to, what's wrong?

我需要帮助从这句话中提取一些单词:

String keywords = "I like to find something vicous in somewhere bla bla bla.\r\n" + 
            "https://address.suffix.com/level/somelongurlstuff";

我的匹配代码看起来有点像这样:

    keywords = keywords.toLowerCase();
    regex = "(I like to find )(.*)( in )(.*)(\.){1}(.*)";
    regex = regex.toLowerCase();
    keywords = keywords.replaceAll(regex, " "); //" ");

我想提取 find in 之间以及 in 和第一个点之间的单词。然而,由于 url 有多个点,一些奇怪的事情开始发生,我得到了我需要的东西加上 url 机智点替换为空格。我希望 url 消失,因为在我的例子中它应该与 (.*) 相匹配,而我在 (\.){1} 之后只需要一个点,所以我想知道发生了什么哪里错了?有什么想法吗?

通过在匹配正则表达式之前添加 (?s) 或删除行中的所有新行字符,您会得到类似的结果:somewhere bla bla bla address suffix something vicious 所以 url 没有点的问题仍然被留在那儿。

不仅仅是关于匹配多行文本。

您需要修复两件事:1) 添加 DOTALL 修饰符,因为您的文本跨越多行;2) 使用惰性点匹配或 - 更有效 - 取反字符 class [^.] 匹配 in:

之后的第一个 . 之前的字符
(?s)(I like to find )(.*)( in )([^.]*)(\.)(.*)
                               ^^^^^^^

regex demo

然而,最好的是 this one:

(?s)(I like to find )(.*?)( in )([^.]*)(\.)(.*)

勉强(惰性)量词使引擎在惰性量化子模式和下一个子模式之间匹配尽可能少的字符。如果我们在( in )之前使用.*,就会发生回溯,即"I like to find "之后的整个字符串都会被regex引擎抓取,然后引擎会向后移动寻找最后 in 。因此,使用 .*? 将匹配 first in .

您可以使用带有勉强量词 *?. 代替 [^.]* 来匹配第一个点,但由于引擎扩展,它在性能方面成本更高尝试将字符串与后续子模式匹配时遇到的每次失败的子模式。

查看我对 Perl regex matching optional phrase in longer sentence 的回答,了解贪婪和懒惰(=不情愿)量词的工作原理。