ChatGPT解决这个技术问题 Extra ChatGPT

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

我有一个字符串列表。其中一些是 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,我想匹配公司以便将其交给进一步处理

J
Johnny Mopp

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

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

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

Lookaround 名称 它的作用 (?=foo) Lookahead 断言紧接在字符串中当前位置之后的是 foo (?<=foo) Lookbehind 断言紧接在字符串中当前位置之前的是 foo (?!foo) 否定Lookahead 断言紧接在字符串中当前位置之后的不是 foo (?


+1 - 在这种情况下,您可以通过使用组 1 而不是组 0 来解决这个问题,但这是一个极好的(和微妙的!)区别。
@Ben Blank:这绝对取决于如何解释“匹配”和“捕获”。
JavaScript 不支持,耶!有一个 JS 友好的方法会很好,但一点也不差,+0.5(四舍五入;D)
喜欢环顾四周的断言!这些也适用于 Ruby。
o
op1ekun

更新:感谢 Germán Rodríguez Herrera!

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

请记住,结果在第 1 组中

Debuggex Demo


T
Thomas

尝试:

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

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


这是不正确的,因为它匹配例如“123-coconut-456”。
以为您希望它更通用...已修复。
p
posdef

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

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

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


评论应该用于改进而不是答案
s
slosd

尝试这个:

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

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

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

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

火柴:

Match 1  apple
Match 2  banana
Match 3

j
johmsp

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


这将匹配 123-apple456,因此不正确。