【问题标题】:Match multiple values in a regex string匹配正则表达式字符串中的多个值
【发布时间】:2014-06-30 16:54:34
【问题描述】:

我试图捕获字符串中的一个或多个变量,而不仅仅是找到的第一个值。我创建了一个测试正则表达式

color.*?(?<COLOR>(red|blue|black)).*?.

和测试句

favorite colors are red, blue and black.  Mr. Green

可以在这里看到http://regex101.com/r/vV7bP3/2

我的目标是让红色、蓝色和黑色中的每一个都匹配,而不是在这段时间之后匹配绿色。换句话说,在带有“颜色”一词的句子中寻找所有颜色的匹配项,但仅限于下一个时期(我知道这是一个由两部分组成的问题,我认为这比发布两次更容易。

【问题讨论】:

    标签: regex


    【解决方案1】:

    要在单词颜色和点之间查找多种颜色,您可以在全局搜索中使用此模式(兼容 PHP/PCRE、Perl、Ruby 2.0、Java、.NET):

    (?:\G(?!\A)|\bcolors?\b)[^.]+?\b(?<colors>red|bl(?:ue|ack))\b
    

    这个想法是使用匹配最后一个匹配结果结尾的\G 锚点。该技术在模式的开头使用两个入口点(在非捕获组中)。

    第一个匹配结果使用单词“color”作为模式的入口点,接下来的匹配结果使用带有\G锚点的入口点。

    由于[^.]是唯一使用的字符类,点后不能得到其他结果。 (请注意,这可能会导致诸如 Mr. 之类的缩写词或 U.S.A. 之类的首字母缩略词出现问题)

    注意:您可以通过在“color”之前添加.*?来减少正则表达式引擎的工作(这样可以避免使用2个入口点逐一测试“color”之前的所有字符):

    (?:\G(?!\A)|.*?\bcolors?\b)[^.]+?\b(?<colors>red|bl(?:ue|ack))\b
    

    或者您可以在开头移动单词边界以更快地失败(因为每个匹配都以单词边界结尾)

    \b(?:\G(?!\A)|colors?\b)[^.]+?\b(?<colors>red|bl(?:ue|ack))\b
    

    【讨论】:

    • 您始终可以依靠 Casimir 的专家解决方案来解决这些问题。 +1 只是想知道这里需要(?!\A)
    • @anubhava 这是为了防止字符串开头出现正匹配。
    • 哦,知道了,所以\G 成功,即使之前没有匹配。
    • @anubhava:完全正确,在第一次尝试时,由于还没有结果,\G 匹配字符串的开头。
    • 非常感谢,这让我大开眼界。不知何故,我有这样的印象,如果没有以前的匹配,\G 将不会成功。
    【解决方案2】:

    您可以尝试下面的正则表达式来捕获文字 . 之前的颜色,

    color[^\.]*(red|blue|black|Green)[^\.]*(red|blue|black|Green)[^\.]*(red|blue|black|Green)[^\.]*
    

    DEMO

    【讨论】:

    • 谢谢,事实上,虽然颜色数组会更大,而且会变得笨拙。我认为有一种方法可以指示多个匹配项。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-10-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-09-02
    • 1970-01-01
    相关资源
    最近更新 更多