如果未找到先前的模式,则忽略 python 正则表达式中的后续模式

Ignore later patterns in python regex if previous patterns are not found

如何匹配一系列组,但后面的组只有在所有先前的组都匹配的情况下才能匹配?

示例:

将不超过 "abc" 的任何字符串与其所属组中的每个字符匹配。

有效:a、ab、abc 无效:b、c、bc、ac

下面的方法可行,但我不确定是否有更好的方法:

^(a)?(?(1)(b)?)(?(2)(c)?)$

也就是说,每场比赛都是可选的,但取决于比赛前的分组。也就是说,'c' 无法匹配,除非 'b' 匹配,除非 'a' 匹配,否则不会发生。

为了帮助以后用谷歌搜索这个的人,我正在解析具有以下格式的 Dicom DateTime

 YYYYMMDDHHMMSS.FFFFFF&ZZXX     # &ZZXX is an optional timezone offset

我使用代码构建了这个正则表达式,而不是像这样输入它。

dicom_dt_parser = re.compile(
    r'^' +
    r'(?P<year>\d{4})' +
    r'(?(year)(?P<month>\d{2})?)' +
    r'(?(month)(?P<day>\d{2})?)' +
    r'(?(day)(?P<hour>\d{2})?)' +
    r'(?(hour)(?P<min>\d{2})?)' +
    r'(?(min)(?P<sec>\d{2})?)' +
    r'(?(sec)(?P<frac>\.\d{1,6})?)' +
    r'(?P<tz>[\+\-]\d{4})?' +
    r'$'
)

dicom_dt_parser.match(datetime_string).groupdict() 将 return 包含所有字段的字典。缺失字段的值为 None.

您所做的非常好,可读性强且简单明了。这也是使用嵌套组构建正则表达式的另一种更短的方法:

^a(b(c)?)?$

Live demo

如果您要接受空输入字符串,您可能需要将 |^$ 附加到上面的正则表达式。

abcdef 的正则表达式为:

^a(b(c(d(e(f)?)?)?)?)?$

您使用此变通方法构建的正则表达式:

^(?P<year>\d{4})(?:(?P<month>\d{2})(?:(?P<day>\d{2})(?:(?P<hour>\d{2})(?:(?P<min>\d{2})(?:(?P<sec>\d{2})(?:(?P<frac>\.\d{1,6})(?P<tz>[+-]\d{4})?)?)?)?)?)?)?$

你自己的正则表达式:

^(?P<year>\d{4})(?(year)(?P<month>\d{2})?)(?(month)(?P<day>\d{2})?)(?(day)(?P<hour>\d{2})?)(?(hour)(?P<min>\d{2})?)(?(min)(?P<sec>\d{2})?)(?(sec)(?P<frac>\.\d{1,6})?)(?P<tz>[\+\-]\d{4})?$

我不会选择这么多反向引用,一个简单的 non-capturing 组和一个 OR 条件对于用例来说应该绰绰有余:

^(a)(?:(b)(c)|(b))?$

Regex101 Demo