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



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

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

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

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

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

通过在正则表达式上匹配之前添加(?s)或删除行上的所有新行字符,可以得到如下内容: somewhere bla bla bla address suffix something vicious 因此,没有点的 url 问题仍然存在。

不仅仅是匹配多行文本。

您需要

解决两件事:1)添加DOTALL修饰符,因为您的文本跨越多行,2)使用惰性点匹配或 - 更有效 - 否定字符类[^.]以匹配字符到in后的第一个.

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

查看正则表达式演示

但是,最好的是这个:

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

不情愿(惰性)量词使引擎在惰性量化子模式和下一个子模式之间匹配尽可能少的字符。如果我们在 ( in ) 之前使用 .* ,就会发生回溯,也就是说,"I like to find "之后的整个字符串会被正则表达式引擎抓取,然后引擎会向后移动寻找最后一个 in 。因此,使用.*?将匹配到第一个 in

您可以使用带有不情愿量词*?.来匹配第一个点,而不是[^.]*,但它在性能方面更昂贵,因为引擎在尝试将字符串与后续子模式匹配时遇到的每次失败时都会扩展子模式。

检查我对较长句子中Perl正则表达式匹配可选短语的回答,以了解贪婪和懒惰(=不情愿)量词的工作原理。

最新更新