简体   繁体   English

帮助 php 中的正则表达式

[英]Help with a regular expression in php

I'm trying to get the following regex pattern to work for the following conditions.我正在尝试使以下正则表达式模式适用于以下条件。 Allowed values are years 1978 or 1978-1979 for 20th and 21st century, so also 2010-2011.对于 20 世纪和 21 世纪,允许的值为 1978 年或 1978-1979 年,2010-2011 年也是如此。 Also if it's 2 years like 1978-1979, they can only be one year apart.此外,如果像 1978-1979 一样是 2 年,它们只能相隔一年。

I have gotten up to the following which is accepting 4 digits /^[1-9]{4}$/ which is pretty basic.我已经完成了以下内容,它接受 4 位数字 /^[1-9]{4}$/ 这是非常基本的。 But any help would be greatly appreciated!但任何帮助将不胜感激!

The only way to do this is in 2 steps.做到这一点的唯一方法是分两步。 First, you'll need to use a regular expression to extract the 2 dates and then you'll need to validate that if there are 2 dates, that they're 1 year apart.首先,您需要使用正则表达式来提取 2 个日期,然后您需要验证是否有 2 个日期,它们相隔 1 年。

Solution:解决方案:

<?php

preg_match('/^((?:19|20)\d{2})(?:-((?:19|20)\d{2}))$/', '1898-1899', $matches);

// Validate a date range
if ( ! empty($matches[2]) && intval($matches[2]) - intval($matches[1]) != 1 )
  die('Invalid date range');
if ( empty($matches[1]) )
  die('Invalid date');

You can ensure that each of the years are from 1900 to 2099 using the regex, but you need to use program logic to validate that the second (optional) year is greater than the first.您可以使用正则表达式确保每一年都是从 1900 年到 2099 年,但您需要使用程序逻辑来验证第二年(可选)是否大于第一年。 Here is a tested function (with a commented regex) to validate the year (or year range):这是一个经过测试的 function(带有注释的正则表达式)来验证年份(或年份范围):

function validYear($yearfield) {
    if (preg_match('/
        # Match a 20th or 21st century year (or range of years).
        ^                # Anchor to start of string.
        (                # $1: Required year.
          (?:19|20)      # Century is 19 or 20.
          [0-9]{2}       # Year is 00 to 99.
        )                # End $1: start year.
        (?:              # Group for optional range part.
          -              # Range part requires - separator.
          (              # $2: Range ending year.
            (?:19|20)    # Century is 19 or 20.
            [0-9]{2}     # Year is 00 to 99.
          )              # End $2: Range ending year.
        )?               # Range part is optional.
        $                # Anchor to end of string.
        /x', $yearfield, $matches))
    {
        $year1 = (int)$matches[1];
        $year2 = isset($matches[2]) ? (int)$matches[2] : $year1 + 1;
        if ($year2 > $year1) return true;
    }
    return false;
}

I don't think this is really the best use for regex, but I like a challenge.我不认为这真的是正则表达式的最佳用途,但我喜欢挑战。

So just to show that anything is possible in regex http://regexr.com?2u843 :所以只是为了表明在正则表达式http://regexr.com?2u843中一切皆有可能:

^(?=[0-9]{4}$|1999-2000|([0-9]{2})[0-8]9-\1[1-9]0|([0-9]{3})[0-8]-\2[1-9])(?:19|20)(?=[^-]*$|([0-9]).*\3.$|09.*10$|19.*20$|29.*30$|39.*40$|49.*50$|59.*60$|69.*70$|79.*80$|89.*90$|99.*00$)[0-9](?=[^-]*$|0.*1$|1.*2$|2.*3$|3.*4$|4.*5$|5.*6$|6.*7$|7.*8$|8.*9$|9.*0$)[0-9](?:-[0-9]{4})?$

Explanation:解释:

^                          # The start of the string
# This piece prevents 1979-1991 and 1989-2000
(?=
[0-9]{4}$|                 #either 4 digits
1999-2000|                 #or 1999-2000
([0-9]{2})[0-8]9-\1[1-9]0| #or first two digits are the same and last digit is 9-0
([0-9]{3})[0-8]-\2[1-9]    #or first three digits are the same
)
#now begins the matching
(?:19|20)                  #Match a 19 or a 20
#This look ahead constricts the to either 4 digits, or to valid transistions for the 3rd digit.
(?=
[^-]*$|                    #No dash
([0-9]).*\3.$|             #Or the same digit
                           #Or one digit apart.
09.*10$|19.*20$|29.*30$|39.*40$|49.*50$|59.*60$|69.*70$|79.*80$|89.*90$|99.*00$
)
[0-9]                      #the third digit.
#This look ahead constricts the to either 4 digits, or to valid transistions for the 3rd digit.
(?=
[^-]*$|                    #No dash
                           #Or one digit apart.
0.*1$|1.*2$|2.*3$|3.*4$|4.*5$|5.*6$|6.*7$|7.*8$|8.*9$|9.*0$
)
[0-9]                      #the 4th digit
(?:-[0-9]{4})?              #the optional second year.
$                          #the end of the string.

This is the regex I came up with:这是我想出的正则表达式:

preg_match('/^(((?:19|20)[0-9]{2})(?:-((?:19|20)[0-9]{2}))?)$/', $string)

It will match either (valid) single years, or double years.它将匹配(有效的)单年或双年。

Capturing group 1 contains the fully matched content (be it 2011 or 2011-2012), group 2 matches the first year, and group 3 matches the second year (if found)捕获组 1 包含完全匹配的内容(无论是 2011 年还是 2011-2012 年),组 2 匹配第一年,组 3 匹配第二年(如果找到)

For the double years: use php to check wether or not they are 1 year apart对于双年:使用 php 检查它们是否相隔 1 年

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

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