如何匹配,但不捕获正则表达式的一部分?

时间:2010-10-13 17:48:21

标签: regex

我有一个字符串列表。其中一些形式为123-...456。可变部分“......”可以是:

  • 字符串“apple”后跟一个连字符,例如123-apple-456
  • 字符串“banana”后跟一个连字符,例如123-banana-456
  • 一个空白字符串,例如123-456(注意只有一个连字符)

“apple”或“banana”以外的任何单词均无效。

对于这三种情况,我想分别匹配“apple”,“banana”和“”。请注意,我从不希望捕获连字符,但我总是希望匹配它。如果字符串不是如上所述的123-...456形式,那么根本就没有匹配。

如何编写正则表达式来执行此操作?假设我有一种风格,允许前瞻,后视,环视和非捕获组。


这里的关键观察是,当你有“苹果”或“香蕉”时,还必须具有尾随连字符,但你不想匹配它。当您匹配空白字符串时,不得具有尾随连字符。我认为封装这个断言的正则表达式是正确的。

7 个答案:

答案 0 :(得分:190)

不捕获内容的唯一方法是使用look-around assertions

(?<=123-)((apple|banana)(?=-456)|(?=456))

因为即使使用non-capturing groups (?:…),整个正则表达式也会捕获匹配的内容。但是这个正则表达式只匹配applebanana如果前面有123-后跟-456,或者它匹配空字符串(如果它前面有123-}然后是456

|Lookaround  |    Name      |        What it Does                       |
-----------------------------------------------------------------------
|(?=foo)     |   Lookahead  | Asserts that what immediately FOLLOWS the |
|            |              |  current position in the string is foo    |
-------------------------------------------------------------------------
|(?<=foo)    |   Lookbehind | Asserts that what immediately PRECEDES the|
|            |              |  current position in the string is foo    |
-------------------------------------------------------------------------
|(?!foo)     |   Negative   | Asserts that what immediately FOLLOWS the |
|            |   Lookahead  |  current position in the string is NOT foo|
-------------------------------------------------------------------------
|(?<!foo)    |   Negative   | Asserts that what immediately PRECEDES the|
|            |   Lookbehind |  current position in the string is NOT foo|
-------------------------------------------------------------------------

答案 1 :(得分:12)

更新:感谢GermánRodríguezHerrera!

在javascript中尝试:/123-(apple(?=-)|banana(?=-)|(?!-))-?456/

请记住,结果在第1组

Debuggex Demo

答案 2 :(得分:8)

尝试:

123-(?:(apple|banana|)-|)456

这将匹配applebanana或空字符串,然后会有0或1个连字符。我不需要捕获组。傻我。

答案 3 :(得分:4)

我修改了其中一个答案(@ op1ekun):

123-(apple(?=-)|banana(?=-)|(?!-))-?456

原因是来自@ op1ekun的答案也匹配"123-apple456",而不是苹果后的连字符。

答案 4 :(得分:2)

试试这个:

/\d{3}-(?:(apple|banana)-)?\d{3}/

答案 5 :(得分:0)

@Gumbo表达式的一种变体,它使用\K来重置匹配位置,以防止在匹配中包含数字块。可用于PCRE正则表达式。

123-\K(?:(?:apple|banana)(?=-456)|456\K)

比赛:

Match 1  apple
Match 2  banana
Match 3

答案 6 :(得分:-2)

到目前为止,最简单的(适用于python)是'123-(apple|banana)-?456'