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

Posted

技术标签:

【中文标题】如何匹配而不是捕获正则表达式的一部分?【英文标题】:How to match, but not capture, part of a regex? 【发布时间】:2011-04-24 23:55:08 【问题描述】:

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

字符串“apple”后跟连字符,例如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 (?:…),整个正则表达式也会捕获它们匹配的内容。但是这个正则表达式只匹配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 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

这将匹配applebanana 或一个空白字符串,并且在它后面会有一个 0 或 1 个连字符。我错了不需要捕获组。傻我。

【讨论】:

这是不正确的,因为它匹配,例如,“123-coconut-456”。 以为您希望它更通用...已修复。【参考方案7】:

试试这个:

/\d3-(?:(apple|banana)-)?\d3/

【讨论】:

这是不正确的,因为它匹配,例如,“123-coconut-456”。 @david:这与您的“香蕉”示例有何不同? @SilentGhost:我想捕获applebanana或“”。正如我所说,所有其他值都是无效的。 sry,在这种情况下:/\d3-(?:(apple|banana)-)?\d3/ 这个例子表明,在不使用前瞻和后瞻的情况下,可以有一个非捕获组。

以上是关于如何匹配而不是捕获正则表达式的一部分?的主要内容,如果未能解决你的问题,请参考以下文章

用于捕获嵌套括号中的值的正则表达式

正则表达式 Match.Value 返回整个值,而不是匹配的组

python中的正则表达式中的 ""

如何使用正则表达式选择除捕获组之外的所有内容?

正则表达式:匹配单个数字重复n次

在正则表达式(Javascript)中分隔捕获组[重复]