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

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

除“苹果”或“香蕉”外的任何词都无效。

对于这三种情况,我想分别匹配“apple”、“banana”和“”。注意,我从来不想捕获连字符,但我总是想匹配它。如果字符串不是123-…如上文所述456,则根本不匹配。

我如何写一个正则表达式来做到这一点?假设我有一个允许前视、后视、后视和非捕获组的样式。


这里的关键观察是,当你有“apple”或“banana”时,你也必须有后面的连字符,但你不想匹配它。当你匹配空白字符串时,你不能有后面的连字符。我认为封装这个断言的正则表达式是正确的。


试试这个:

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

试一试:

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

它将匹配apple、banana或空白字符串,后面将有一个0或1连字符。我错了,我不需要一个捕捉组。愚蠢的我。

唯一不捕获的方法是使用环视断言:

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

因为即使使用非捕获组(?:…),整个正则表达式也会捕获它们匹配的内容。但是这个正则表达式只匹配apple或banana,如果它前面有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 Lookahead Asserts that what immediately FOLLOWS the current position in the string is NOT foo
(?<!foo) Negative Lookbehind Asserts that what immediately PRECEDES the current position in the string is NOT foo

在javascript中尝试:/ 123 -(苹果(? = -)|香蕉 (?=-)|(?!-))-?456 /

记住,结果在第1组

Debuggex演示


根据Germán Rodríguez Herrera提供的输入

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

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

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

原因是@op1ekun的答案也匹配“123-apple456”,在apple后面没有连字符。

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

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

匹配:

Match 1  apple
Match 2  banana
Match 3