PHP正则表达式非捕获非匹配组

时间:2011-05-10 03:11:13

标签: php regex date preg-match match

我正在制作一个与正则表达式相匹配的日期,而且一切都很顺利,到目前为止我已经有了这个:

"/(?:[0-3])?[0-9]-(?:[0-1])?[0-9]-(?:20)[0-1][0-9]/"

它(希望)将匹配单个或两位数的日期和月份,以及21世纪的两倍或四倍数字年份。到目前为止,一些试验和错误让我受益匪浅。

但是,我对这些结果有两个简单的问题:

  1. (?: )这是一个简单的解释?显然,这是一个不匹配的群体。但是......

  2. 什么是尾随??例如(? )?

3 个答案:

答案 0 :(得分:30)

[编辑(再次)改进格式并修复介绍。]

这是评论和答案。

答案部分......我同意亚历克斯先前的回答。

  1. (?: )( )形成对比,用于避免捕获文本,通常是为了减少您想要的后向引用或提高速度性能。

  2. ?在(?: )之后 - 或在关注除* + ?{}之外的任何内容时 - 表示在合法匹配中可能找到或未找到前一项。例如,/z34?/将匹配z3以及z34,但它不匹配z35或z等。

  3. 评论部分......我做了一些可能被认为是对你正在进行的正则表达式的改进:

    (?:^|\s)(0?[1-9]|[1-2][0-9]|30|31)-(0?[1-9]|10|11|12)-((?:20)?[0-9][0-9])(?:\s|$)
    

    - 首先,它避免了像0-0-2011这样的事情

    - 其次,它避免了像233443-4-201154564

    这样的事情

    - 第三,它包括1-1-2022之类的东西

    - 第四,它包括1-1-11

    之类的东西

    - 第五,它避免了像34-4-11

    这样的事情

    - 第六,它允许你捕获日,月和年,这样你就可以更容易地在代码中引用这些代码。例如,可以进行进一步检查的代码(是第二个被捕获的组2和是第一个被捕获的组29,这是闰年,或者第一个被捕获的组是< 29),以便查看某个29日期是否合格。

    最后,请注意您仍会获得不存在的日期,例如31-6-11。如果你想避免这些,请尝试:

    (?:^|\s)(?:(?:(0?[1-9]|[1-2][0-9]|30|31)-(0?[13578]|10|12))|(?:(0?[1-9]|[1-2][0-9]|30)-(0?[469]|11))|(?:(0?[1-9]|[1-2][0-9])-(0?2)))-((?:20)?[0-9][0-9])(?:\s|$)
    

    另外,我假设日期之前和之后是空格(或者行/结尾),但你可能想要调整它(例如,允许标点符号)。

    其他地方的评论者引用了您可能会觉得有用的资源: http://rubular.com/

答案 1 :(得分:6)

  1. 这是一个非捕获组。你不能回来参考它。通常用于整理反向引用和/或提高性能。
  2. 这意味着之前的捕获组是可选的。

答案 2 :(得分:3)

<强>子模式

子图案由括号(圆括号)分隔,可以嵌套。将模式的一部分标记为子模式可以做两件事:

  1. 它定位了一组替代品。例如,模式 cat(aract | erpillar |)匹配其中一个单词&#34; cat&#34;,&#34; cataract&#34;,或者 &#34;毛虫&#34 ;.没有括号,它将匹配&#34; cataract&#34;, &#34; erpillar&#34;或空字符串。
  2. 它将子模式设置为捕获子模式(如定义的那样) 以上)。当整个模式匹配时,主题的那部分 与子模式匹配的字符串将通过传递回调用方 pcre_exec()的ovector参数。计算开括号 从左到右(从1开始)获取数字 捕获子模式。
  3. 例如,如果字符串&#34;红色王&#34;匹配模式((红|白)(王|女王))捕获的子串是&#34;红王&#34;,&#34;红&#34;和&#34;王&#34; ,编号为1,2和3。

    普通括号实现两个功能的事实并不总是有用的。有时候需要分组子模式而没有捕获要求。如果左括号后跟&#34;?:&#34;,则子模式不执行任何捕获,并且在计算任何后续捕获子模式的数量时不计算。例如,如果字符串&#34;白色女王&#34;与((?:红色|白色)(王|女王))模式匹配被捕获的子串是&#34;白色女王&#34;并且&#34; queen&#34;,并且编号为1和2.捕获的子串的最大数量是65535.但是,根据libpcre的配置选项,可能无法编译这样的大型模式。

    作为一种方便的简写,如果在非捕获子模式的开头需要任何选项设置,则选项字母可能出现在&#34;?&#34;和&#34;:&#34;。因此这两种模式

    (?i:saturday|sunday)
    (?:(?i)saturday|sunday)
    

    匹配完全相同的字符串集。因为从左到右尝试了替代分支,并且在到达子模式结束之前不重置选项,所以一个分支中的选项设置确实会影响后续分支,因此上述模式匹配&#34; SUNDAY&#34;以及&#34;星期六&#34;。

    可以使用语法(?Ppattern)命名子模式。然后,此子模式将通过其正常数字位置和名称在matches数组中编制索引。 PHP 5.2.2引入了两种替代语法(?pattern)和(?&#39; name&#39; pattern)。

    有时需要在正则表达式中具有多个匹配但交替的子组。通常情况下,这些中的每一个都会得到自己的反向引用数,即使其中只有一个可能匹配。为了解决这个问题,(?|语法允许重复数字。考虑以下正则表达式匹配字符串星期日:

    (?:(Sat)ur|(Sun))day
    

    这里Sun存储在反向引用2中,而反向引用1则为空。匹配产生Sat在反向引用1,而反向引用2不存在。更改模式以使用(?|修复此问题:

    (?|(Sat)ur|(Sun))day
    

    使用此模式,Sun和Sat都将存储在反向引用1中。

    参考:http://php.net/manual/en/regexp.reference.subpatterns.php