我有一个字符串列表。其中一些是 123-...456
的形式。可变部分“...”可能是:
字符串 "apple" 后跟一个连字符,例如 123-apple-456
字符串 "banana" 后跟连字符,例如 123-banana-456
一个空白字符串,例如 123-456(注意只有一个连字符)
“apple”或“banana”以外的任何词都是无效的。
对于这三种情况,我想分别匹配“apple”、“banana”和“”。请注意,我从不希望 capture 连字符,但我总是希望 match 它。如果字符串不是上述 123-...456
的形式,则根本不存在匹配项。
我如何编写一个正则表达式来做到这一点?假设我有一种允许前瞻、后瞻、环顾和非捕获组的风格。
这里的关键观察是,当您有“apple”或“banana”时,您还必须有尾随连字符,但您不想匹配它。当你匹配空白字符串时,你不能有尾随连字符。我认为,封装此断言的正则表达式将是正确的。
不捕获某些内容的唯一方法是使用 look-around assertions:
(?<=123-)((apple|banana)(?=-456)|(?=456))
因为即使使用 non-capturing groups (?:…)
,整个正则表达式也会捕获它们匹配的内容。但是这个正则表达式只匹配 apple
或 banana
,如果它前面是 123-
,后面是 -456
,或者它匹配空字符串,如果它前面是 123-
,后面是 456
。
Lookaround 名称 它的作用 (?=foo) Lookahead 断言紧接在字符串中当前位置之后的是 foo (?<=foo) Lookbehind 断言紧接在字符串中当前位置之前的是 foo (?!foo) 否定Lookahead 断言紧接在字符串中当前位置之后的不是 foo (?
更新:感谢 Germán Rodríguez Herrera!
在 javascript 中尝试:/123-(apple(?=-)|banana(?=-)|(?!-))-?456/
请记住,结果在第 1 组中
尝试:
123-(?:(apple|banana|)-|)456
这将匹配 apple
、banana
或空白字符串,并且在其后面会有 0 或 1 个连字符。我错了不需要捕获组。傻我。
我修改了一个答案(@op1ekun):
123-(apple(?=-)|banana(?=-)|(?!-))-?456
原因是来自@op1ekun 的答案也匹配 "123-apple456"
,而苹果后面没有连字符。
尝试这个:
/\d{3}-(?:(apple|banana)-)?\d{3}/
apple
或 banana
或“”。正如我所说,所有其他值都是无效的。
@Gumbo 的表达式变体,它使用 \K
重置匹配位置以防止在匹配中包含数字块。可用于 PCRE 正则表达式风格。
123-\K(?:(?:apple|banana)(?=-456)|456\K)
火柴:
Match 1 apple
Match 2 banana
Match 3
到目前为止,最简单的(适用于 python)是 '123-(apple|banana)-?456'
。
123-apple456
,因此不正确。