如何使用正则表达式使用尽可能少的组以匹配尽可能长的字符串

时间:2018-07-28 05:06:58

标签: regex

例如,这是正则表达式

([a]{2,3})

这是字符串

aaaa // 1 match "(aaa)a" but I want "(aa)(aa)"
aaaaa // 2 match "(aaa)(aa)"
aaaaaa // 2 match "(aaa)(aaa)"

但是,如果我更改了正则表达式

([a]{2,3}?)

那么结果是

aaaa // 2 match "(aa)(aa)"
aaaaa // 2 match "(aa)(aa)a" but I want "(aaa)(aa)"
aaaaaa // 3 match "(aa)(aa)(aa)" but I want "(aaa)(aaa)"

我的问题是,可以使用尽可能少的组来匹配尽可能长的字符串吗?

3 个答案:

答案 0 :(得分:1)

怎么样呢?

(a{3}(?!a(?:[^a]|$))|a{2})

这会寻找 字符a三次(而不是一个a和另一个字符) 或{ {1}}两次。

故障:

a

这里是demo

请注意,如果您不需要捕获组,则实际上可以使用整个匹配,而无需将捕获组转换为非捕获组:

(                   # Start of the capturing group.
    a{3}            # Matches the character 'a' exactly three times.
    (?!             # Start of a negative Lookahead.
        a           # Matches the character 'a' literally.
        (?:         # Start of the non-capturing group.
            [^a]    # Matches any character except for 'a'.
            |       # Alternation (OR).
            $       # Asserts position at the end of the line/string.
        )           # End of the non-capturing group.
    )               # End of the negative Lookahead.
    |               # Alternation (OR).
    a{2}            # Matches the character 'a' exactly two times.
)                   # End of the capturing group.

Which would look like this

答案 1 :(得分:1)

尝试此正则表达式:

^(?:(a{3})*|(a{2,3})*)$

Click for Demo

说明:

  • ^-断言行的开头
  • (?:(a{3})*|(a{2,3})*)-一个非捕获组,包含2个由OR运算符分隔的子序列
    • (a{3})*-第一个子序列尝试匹配3次出现的a。末尾的*允许此子序列匹配0或3或6或9。...在行尾之前出现a
    • |-或
    • (a{2,3})*-尽可能多地匹配2至3次出现的a。末尾的*会在行尾之前重复0次以上

-$-声明行的结尾

答案 2 :(得分:1)

试试这个简短的正则表达式:

a{2,3}(?!a([^a]|$))

Demo

如何制作:

我从这个简单的正则表达式开始:a{2}a?。它寻找2个连续的a's,之后可能是另一个a。如果2个a's 后跟另一个a,则它与所有三个a's匹配。

这适用于大多数情况:

enter image description here

但是,在以下情况下失败:

enter image description here

所以现在,我知道我必须以某种方式修改我的正则表达式,使其仅在第三个a之后没有a的情况下才与第三个a([^a]|$)匹配。所以现在,我的正则表达式看起来像a{2}a?(?!a([^a]|$)),它适用于所有情况。然后我将其简化为a{2,3}(?!a([^a]|$))

就是这样。

enter image description here

编辑

如果您想要捕获行为,则在正则表达式周围添加括号,例如:

(a{2,3}(?!a([^a]|$)))