2011-05-10 78 views
13

我正在做一个日期匹配正则表达式,而这一切都做得较好,我得到这个至今:PHP正则表达式非捕获不匹配组

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

它(希望)单相匹配或在二十一世纪的两位数天和几个月,以及两位或四位数年份。一些试验和错误已经让我走到了尽头。

但是,我已经得到了关于这些结果两个简单的问题:

  1. (?:)究竟是什么简单的解释?显然它是一个不匹配的组。但是...

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

回答

25

[编辑(再)来改善格式和固定介绍]

这是一条评论和答复。

答案部分......我同意亚历克斯的早期回答。

  1. (?:),而相比之下,(),是为了避免在拍摄文字,一般以少回抛出这些引用你想或者提高速度性能。

  2. The?在(?:)之后 - 或者在跟随* + ?{}之后的任何情况时 - 表示前面的项目可能在合法匹配中找到或可能找不到。例如,/z34?/将匹配Z3和Z34,但它不会匹配Z35或Z等

的注释部分... ...我做什么可能被认为是改善你工作的正则表达式:

(?:^|\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-202 2

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

- 第五,它避免了之类的东西34-4-11

- 第六,它可以让你拍摄的日子,月份和年份,以便您可以在代码中更轻松地查看这些内容。例如,将进行进一步检查的代码(是第二个捕获组2,并且是第一个捕获组29并且这是闰年,或者是第一个捕获组是< 29),以便查看feb 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|$) 

而且,我认为会的日期用一个空格的前面和后面(或者乞求/行尾),但您可能想OT调整的是(例如,以允许标点符号)。

一个评论者引用的其他这种资源,你可能会发现有用: http://rubular.com/

+0

第一部分内容非常全面,非常全面和有帮助。我正在使用'/ [0-3]?[0-9] - [0-1]?[0-9] - (?: 20)?[0-1] [0-9] /'然后在组件上运行'checkdate()'来处理假日期。 – Ben 2011-05-10 06:10:51

6
  1. 它是一种非捕获组。你不能回引用它。通常用于清理反向引用和/或提高性能。
  2. 这意味着上一个捕获组是可选的。
+0

Groovy。对于未来的用户来说,这是一个半帮助的进一步解释:http://www.regular-expressions.info/named.html – Ben 2011-05-10 03:26:31

3

子模式

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

  1. 它本地化了一套备选方案。例如,猫(aract | erpillar |)的图案 与单词“猫”,“白内障”或 “毛毛虫”中的一个匹配。没有括号,它会匹配“白内障”, “erpillar”或空字符串。
  2. 它将子模式设置为捕获子模式(如上面定义的 )。当整个模式匹配时,与子模式匹配的主题 字符串的部分将通过 pcre_exec()的ovector参数传回给调用者。从左向右(从1开始)将开括号计数为 ,以获得捕获子模式的 的编号。

例如,如果字符串“红王”与图案匹配((白)(皇后)),则捕获的子串是“红色王”,“红色”和“王“,并且被编号为1,2和3.

简单括号实现两个功能的事实并不总是有帮助的。常常需要一个分组子模式而没有捕获需求。如果左括号后面跟着“?:”,则子模式不执行任何捕获,并且在计算任何后续捕获子模式的数量时不计算。例如,如果字符串“白皇后”与图案匹配,则捕获的子串是“白皇后”和“皇后”,并且被编号为1和2 。捕获的子字符串的最大数量是65535.但是,根据libpcre的配置选项,可能无法编译如此大的模式。

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

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

匹配完全相同的一组字符串。由于可选分支从左到右进行尝试,直到达到子模式结束时才会重置选项,因此一个分支中的选项设置会影响后续分支,因此上述模式与“星期日”以及“星期六”匹配。

使用语法(?Ppattern)可以命名子模式。然后,这个子模式将通过正常的数字位置和名称在匹配数组中进行索引。 PHP 5.2。2引入了两种替代语法(?模式)和(?'名称'模式)。

有时需要在正则表达式中具有多个匹配但交替的子组。通常情况下,每个人都会得到自己的反向引用号码,尽管他们中只有一个可能会匹配。 ?为了克服这个问题,(|语法允许有重复号考虑对字符串周日匹配以下正则表达式:

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

这里太阳被存储在反向引用2,而引用1是空的匹配产生坐在后向引用。 1,而逆向引用2不存在变着花样使用(|修复了这个问题:?

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

地使用这种模式,Sun和周六都将存储在反向引用1.

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