如何匹配而不是捕获正则表达式的一部分?
Posted
技术标签:
【中文标题】如何匹配而不是捕获正则表达式的一部分?【英文标题】:How to match, but not capture, part of a regex? 【发布时间】:2011-04-24 23:55:08 【问题描述】:我有一个字符串列表。其中一些是123-...456
的形式。可变部分“...”可能是:
123-apple-456
字符串“banana”后跟连字符,例如123-banana-456
一个空白字符串,例如123-456
(注意只有一个连字符)
“apple”或“banana”以外的任何单词都是无效的。
对于这三种情况,我想分别匹配“apple”、“banana”和“”。请注意,我从不希望 capture 连字符,但我总是希望 match 它。如果字符串不是上述123-...456
的形式,则根本不匹配。
如何编写正则表达式来执行此操作?假设我的风格允许前瞻、后瞻、环顾和非捕获组。
这里的关键观察是,当你有“apple”或“banana”时,你还必须有尾随连字符,但你不想匹配它。当您匹配空白字符串时,您不得有尾随连字符。我认为,封装此断言的正则表达式将是正确的。
【问题讨论】:
您想匹配除连字符以外的所有内容? 我有一个更简单的例子,我有 me@company.org,我想匹配公司以便将其交给进一步处理 【参考方案1】:不捕获某些东西的唯一方法是使用look-around assertions:
(?<=123-)((apple|banana)(?=-456)|(?=456))
因为即使使用non-capturing groups (?:…)
,整个正则表达式也会捕获它们匹配的内容。但是这个正则表达式只匹配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 |
【讨论】:
+1 — 在这种情况下,您可以通过使用组 1 而不是组 0 来解决这个问题,但这是一个极好的(和微妙的!)区别。 @Ben Blank:这绝对取决于如何解释“匹配”和“捕获”。 javascript 不支持,耶!有一个对 JS 友好的方法会很好,但一点也不差,+0.5(四舍五入 ;D) 喜欢环顾四周的断言!这些也适用于 Ruby。【参考方案2】:@Gumbo 表达式的变体,它利用 \K
重置匹配位置以防止在匹配中包含数字块。可用于 PCRE 正则表达式。
123-\K(?:(?:apple|banana)(?=-456)|456\K)
匹配:
Match 1 apple
Match 2 banana
Match 3
【讨论】:
【参考方案3】:更新:感谢 Germán Rodríguez Herrera!
在 javascript 中尝试:/123-(apple(?=-)|banana(?=-)|(?!-))-?456/
记住结果在第 1 组
Debuggex Demo
【讨论】:
【参考方案4】:我已经修改了一个答案(@op1ekun):
123-(apple(?=-)|banana(?=-)|(?!-))-?456
原因是来自@op1ekun 的答案也匹配"123-apple456"
,但apple 后面没有连字符。
【讨论】:
评论应该用于改进而不是答案【参考方案5】:到目前为止,最简单的(适用于 python)是'123-(apple|banana)-?456'
。
【讨论】:
这会匹配123-apple456
所以它不正确。【参考方案6】:
试试:
123-(?:(apple|banana|)-|)456
这将匹配apple
、banana
或一个空白字符串,并且在它后面会有一个 0 或 1 个连字符。我错了不需要捕获组。傻我。
【讨论】:
这是不正确的,因为它匹配,例如,“123-coconut-456”。 以为您希望它更通用...已修复。【参考方案7】:试试这个:
/\d3-(?:(apple|banana)-)?\d3/
【讨论】:
这是不正确的,因为它匹配,例如,“123-coconut-456”。 @david:这与您的“香蕉”示例有何不同? @SilentGhost:我只想捕获apple
或banana
或“”。正如我所说,所有其他值都是无效的。
sry,在这种情况下:/\d3-(?:(apple|banana)-)?\d3/
这个例子表明,在不使用前瞻和后瞻的情况下,可以有一个非捕获组。以上是关于如何匹配而不是捕获正则表达式的一部分?的主要内容,如果未能解决你的问题,请参考以下文章