【问题标题】:Regular expression: Sequence of optional but dependent matches without nesting groups正则表达式:没有嵌套组的可选但依赖匹配的序列
【发布时间】:2016-07-12 08:51:04
【问题描述】:

我正在编写一个正则表达式来匹配 MySQL 在分配给 DATETIME 列时接受的字符串。

正则表达式需要匹配这些字符串:

2016-07-12 06:32:54.0001
2016-07-12 06:32:54.
2016-07-12 06:32:54
2016-07-12 06:32:
2016-07-12 06:32
2016-07-12 06:
2016-07-12 06
2016-07-12 
2016-07-12

但不应匹配这些字符串:

2016-07-12 06:32:.0001
2016-07-12 06::54.0001
2016-07-12 :32:54.0001
2016-07-12 ::.

也就是说,中间空格之后的每个部分都是可选的,但是每个可选的部分都依赖于前面的部分(正则表达式只能跳过其余部分直接到最后)。

目前我有:

/^
(\d+) # year
[[:punct:]]
(\d+) # month
[[:punct:]]
(\d+) # day
(?:
    (?:T|\s+|[[:punct:]]) # seperator between date and time
    (?:
        (\d+) # hour
        (?:
            [[:punct:]]
            (?:
                (\d+) # minute
                (?:
                    [[:punct:]]
                    (?:
                        (\d+) # second
                        (?:
                            \.
                            (\d+)? # microsecond
                        )?
                    )?
                )?
            )?
        )?
    )?
)?
$/xDs

有没有办法避免深度嵌套的组?

谢谢

【问题讨论】:

  • 如果需要使用捕获的值,没有办法简化。如果它是 PCRE 正则表达式,您可以通过将 [[:punct:]] 替换为 \p{P} 来稍微缩短它。
  • 嵌套组似乎是您的问题最自然的解决方案。命名的捕获组可能会使正则表达式更清晰。根据您的语言,您可能更喜欢编写多个正则表达式,并在匹配它们时使用标记(例如用空字符串替换它们)。
  • 这将允许您在不嵌套的情况下分成组:([^\-\s\.\:]{2,4})[\-\s\.\:] 缺点是您无法识别错误的情况,可能会分成不同的正则表达式以检查是否没有重复的分隔符。
  • 用例是什么,顺便说一句?我看不出缩短这个正则表达式的意义。众所周知,好的、高效的正则表达式既复杂又长。
  • 为什么要担心“深度嵌套”? logic 是嵌套的,所以 pattern 也嵌套是合理的。有用。离开吧。

标签: regex


【解决方案1】:

如果您想在结果中保留捕获的值,您的问题的答案是

为什么? Capturing repeated groups is not supported in PCRE。此外,如果您使用任何类型的(?:(PATTERN_BLOCK)PATTERN_BLOCK2){n},您只会得到最终的PATTERN_BLOCK 值。如果您考虑过(?(DEFINE)....)capturing groups inside that block are also reset,那么您将无法访问这些值。

这些带有“嵌套”捕获组的可选组正是您在这种情况下所需要的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-06-06
    • 1970-01-01
    • 2020-06-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多