【问题标题】:Help with a regular expression in php帮助 php 中的正则表达式
【发布时间】:2011-07-15 16:15:33
【问题描述】:

我正在尝试使以下正则表达式模式适用于以下条件。对于 20 世纪和 21 世纪,允许的值为 1978 年或 1978-1979 年,2010-2011 年也是如此。另外,如果像 1978-1979 一样是 2 年,它们只能相隔一年。

我已经完成了以下内容,即接受 4 位数字 /^[1-9]{4}$/ 这是非常基本的。但任何帮助将不胜感激!

【问题讨论】:

  • 我不认为正则表达式是正确的工具,尤其是。 “相隔一年”规则...
  • 解释了这么多逻辑,这在合理的正则表达式中是无法实现的。我建议最多验证格式并使用正则表达式解析日期,然后执行其余的逻辑。
  • 是的...获取一个正则表达式来获取日期,然后使用良好的 ole PHP 逻辑来检查您的其他约束。

标签: php regex


【解决方案1】:

您可以使用正则表达式确保每一年都是从 1900 年到 2099 年,但您需要使用程序逻辑来验证第二年(可选)是否大于第一年。这是一个经过测试的函数(带有注释的正则表达式),用于验证年份(或年份范围):

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;
}

【讨论】:

  • 非常感谢您的回答。非常有据可查!很好的答案,我只是修改 year2 以在未设置 match[2] 的情况下返回 null 并检查 year2 和 year1 之间的差异是否仅为 1 以便返回 true。再次非常感谢您。
  • 如果一切都使用“正常”的程序逻辑来完成,这个函数会不会更具可读性?我的意思是,您已经在比较数字 ints,为什么不简单地在 - 上爆炸,然后创建 ints 并从那里开始?
【解决方案2】:

执行此操作的唯一方法是分两步。首先,您需要使用正则表达式来提取 2 个日期,然后您需要验证是否有 2 个日期,它们相隔 1 年。

解决方案:

<?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');

【讨论】:

  • 那么 20 世纪的乱码呢?
  • @sdolgy - 20 世纪的日期是从 1900 年到 1999 年。它们也是4位数。你的意思是两位数的日期吗?
  • @sdolgy - 我更新了正则表达式,只允许以 19 和 20 开头的日期(例如 1999 或 2011)。
【解决方案3】:

我不认为这真的是正则表达式的最佳用途,但我喜欢挑战。

所以只是为了表明在正则表达式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})?$

解释:

^                          # 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.

【讨论】:

    【解决方案4】:

    这是我想出的正则表达式:

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

    它将匹配(有效的)单年或双年。

    捕获组 1 包含完全匹配的内容(无论是 2011 年还是 2011-2012 年), 第 2 组匹配第一年,第 3 组匹配第二年(如果找到)

    对于双年:使用php检查他们是否相隔1年

    【讨论】:

    • 伙计,你太棒了..!!!我很想知道您是否可以在阅读材料上为我指明正确的方向,以便在这个主题上更加先进。否则..非常感谢您的帮助,非常感谢。!
    • @Ron 你可以从this tutorial开始。非常好,如果您要经常使用正则表达式,您可能要考虑购买他们的软件之一,RegexBuddy。它可以帮助您创建、测试正则表达式并将其导出到多种不同的编程语言。
    猜你喜欢
    • 2011-10-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-10
    相关资源
    最近更新 更多