regex 如何使一个正则表达式捕获组是可选的,但要成对?

yks3o0rb  于 2022-12-24  发布在  其他
关注(0)|答案(2)|浏览(99)

我试图捕捉以下情况

John;123 = John and 123
`John;123` = John and 123
"John;123" = John and 123
John;John;123 = John;John and 123
`John;123 = `John and 123
John;123' = No capture

所以我有下面的正则表达式模式:(?:'|")(.*);([0-9].+)(?:'|"),它可以很好地处理引号和分号捕获组。
但是我在把引号作为一对可选的时候遇到了麻烦,也就是说,要么你把外面的引号都算进去,要么你不算。
如果您不计算它们,那么它们实际上是名称的一部分,不应该作为外部捕获组包括在内。
我尝试将它们设置为可选,如下所示:(?:'|")?(.*);([0-9].+)(?:'|")?,但随后模式被错误地捕获为:

`John;123 = John and 123

当它应该

`John;123 = `John and 123

因为它不是一对引号,所以引号是名称的一部分
有什么想法吗?

fwzugrvs

fwzugrvs1#

如果不允许在捕获组中使用所需的任何引号,则可以使用带有反向引用的捕获组来匹配任何引号。
感兴趣的捕获组值在组2和组3中。

(?<!\S)([`"']?)([^\s;]+(?:;[^\s;`"']+)*);([^\s;`"']+)\1(?!\S)

Regex demo

jchrr9hc

jchrr9hc2#

这是我能得到的最接近的版本。不确定是否有更好的版本,但这似乎是工作。
我实际上是用一个OR语句|连接两个不同的正则表达式模式,因为似乎有不止一个模式在起作用,这使得这个特定的需求非常具有挑战性。
第一个模式查找引号内的模式,第二个模式查找引号外的模式。

第一个模式如下所示:

^(?>`|")([A-Za-z]+)(?>;)([0-9]+)(?>`|")$

第二个模式如下所示:

^(`?[A-Za-z]+)(?>;)([A-Za-z]+)?;?([0-9]+)$

当您使用OR语句将它们组合在一起时,将得到以下结果:

最终正则表达式:

^(?>`|")([A-Za-z]+)(?>;)([0-9]+)(?>`|")$|^(`?[A-Za-z]+)(?>;)([A-Za-z]+)?;?([0-9]+)$

参见Demo

相关问题