Regex:可选的子字符串,它可以出现在两个位置之一中,但不能同时出现在两个位置中

问题描述 投票:0回答:2

我正在验证带有正则表达式,PCRE风格的字符串。我有一个子字符串,可以选择出现在两个可能的位置之一中-但不能同时出现在两个位置中。我该如何为此编写正则表达式?

没有子字符串的正则表达式为

M[01]([ ]*\(?[A-Z]{3}\)?)?

子字符串具有正则表达式C [0-5],可以在括号之前或之后出现,或根本不出现。它可以用空格分隔,也可以不分隔。

有效示例(为了清晰起见,都包含空格,但没有空格的相同示例也是有效的:

M1
M1 C1
M1 (OSS)
M1 C1 (OSS)
M1 (OSS) C1

无效示例:

M1 C1 (OSS) C1

我想出的最接近的是

M[01]([ ]*C[1-5]?)([ ]*\(?[A-Z]{3}\)?)?([ ]*C[1-5]?)

但是这也会接受无效的示例。因为我只有两个职位,所以我当然可以列举不同的组合,但是我不喜欢该解决方案,因为它不能很好地扩展到更多可能的职位。

[如果这很重要,那么这是一个将在更长的字符串中待验证的组,因此正则表达式将作为子例程嵌入到更大的字符串中。

regex pcre
2个回答
1
投票

一个选项是,(如果)匹配第一个C部分时,capture捕获组中的C。然后,在可能的C部分的第二个位置,在匹配它之前先对第一个捕获组进行负前瞻:

^M[01](?: *(C)[1-5])? *(?:\(?[A-Z]{3}\)?(?: *(?!\1)C[1-5])?)?$
           ^^^                                ^^^^^

https://regex101.com/r/xCxSn4/1

[注意,如果要匹配一个普通空格,则只需在模式中使用一个普通空格,不需要字符集:例如([ ])等效于( )


0
投票

使用pcre,另一种选择是利用conditional检查是否存在形式为1的组。

(?(1)foo|bar)

对于示例数据,您可以将所有3个部分设为可选,其中第一部分是捕获组。如果没有捕获组1,则匹配最后一部分。

^M[01](\h*C[1-5])?(?:\h*\([A-Z]{3}\))?(?(1)|(?:\h*C[1-5])?)$

说明

  • [^字符串的开头
  • [M[01]匹配M并且为0或1
  • (捕获组1
    • [\h*C[1-5]匹配0+水平空白字符和C到1-5的数字]
  • [)?关闭组1并使其为可选]
  • (?:非捕获组
    • [\h*\([A-Z]{3}\)匹配0+水平空白字符和A-Z之间的3次之间
  • )?关闭组并将其设为可选
  • (? If子句
    • (1)测试捕获组1是否存在。如果有,则什么也不做
    • |
    • [(?:\h*C[1-5])?可选地将0+水平空白字符和C与数字1-5匹配
  • [) Close if子句
  • [$字符串结尾

Regex demo

请注意,在您尝试的模式中,匹配左括号和右括号是可选的\)?,也可以匹配M1 (OSS)。不知道这是否是预期的匹配项,但我已将该部分省略。

© www.soinside.com 2019 - 2024. All rights reserved.