繁体   English   中英

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

[英]PHP regex non-capture non-match group

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

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

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

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

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

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

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

这是一个评论和答案。

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

  1. (?: ) :)与( )相反,用于避免捕获文本,通常是为了减少所需的后向引用,或者提高速度性能。

  2. 的? (?: ) - 或除了* + ?之外的任何事情* + ? {} - 表示在合法匹配中可能找到或未找到前面的项目。 例如, /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-2022之类的东西

- 第四,它包括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|$)

此外,我假设日期之前和之后是一个空格(或乞讨/结束行),但您可能想要调整它(例如,允许标点符号)。

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

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

子模式

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

  1. 它本地化了一系列替代品。 例如,模式cat(aract | erpillar |)匹配单词“cat”,“cataract”或“caterpillar”中的一个。 如果没有括号,它将匹配“cataract”,“erpillar”或空字符串。
  2. 它将子模式设置为捕获子模式(如上所述)。 当整个模式匹配时,主题字符串中与子模式匹配的那部分将通过pcre_exec()的ovector参数传递回调用者。 从左到右(从1开始)计算开括号以获得捕获子模式的编号。

例如,如果字符串“the red king”与模式匹配((red | white)(king | queen))捕获的子串是“red king”,“red”和“king”,并且编号1,2和3。

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

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

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

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

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

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

(?:(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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM