为什么这个正则表达式有效?

时间:2014-01-22 15:57:52

标签: regex

我想从日期时间偏移值中删除(CDT)。我在下面编写了简单的正则表达式这样做,它按原来的预期工作,但写完之后我就不知道为什么会这样。为什么结果不会在2012年停止?

原始字符串: "Thu, 02 Aug 2012 07:42:02 -1525 (CDT)"

正则表达式: .*\d{4}

结果: "Thu, 02 Aug 2012 07:42:02 -1525"

6 个答案:

答案 0 :(得分:5)

它有效,因为.*greedy

这意味着,.*在做其他事情之前会尽可能多地匹配。

当正则表达式适用时,.*匹配整个事物,因为它是贪婪的:

  

星期四,2012年8月2日07:42:02 -1525(CDT)

然后尝试匹配\d{4},但不幸的是,它不匹配任何东西,因为它在最后。因此,正则表达式(.*部分)将回溯(返回并返回之前匹配的内容),每次一个字符,每次检查\d{4}

  

星期四,2012年8月2日07:42:02 -1525(CDT )[不匹配]​​

     

星期四,2012年8月2日07:42:02 -1525(CD T)[不匹配]​​

     

星期四,2012年8月2日07:42:02 -1525(C DT)[不匹配]​​

     

星期四,2012年8月2日07:42:02 -1525( CDT)[不匹配]​​

     

星期四,2012年8月2日07:42:02 -1525 (CDT)[不匹配]​​

     

星期四,2012年8月2日07:42:02 -1525 (CDT)[不匹配]​​

     

...

     

星期四,2012年8月2日07:42:02 - 1525(CDT)

此时,它可以匹配\d{4},这就是它将要执行的操作:

  

星期四,2012年8月2日07:42:02 -1525 (CDT)

由于正则表达式中没有其他内容,因此将在此结束。

答案 1 :(得分:4)

量词*是贪婪的。这意味着它将尽可能匹配。

这就是\d{4}1525匹配,.*与之前的字符匹配的原因。

如果您使用延迟量词*?,那么在尝试更长的序列之前,它将首先与最小数量的字符匹配。在这种情况下,它会\d{4}2012匹配。

答案 2 :(得分:2)

模式.*\d{4}匹配零个或多个字符(贪婪)后跟4个数字的任何序列。

它的工作原理是因为它匹配字符串中最后四位数的所有内容(1525)并忽略字符串的剩余部分。

请注意,您的模式有点危险。如果您的输入缺少时区偏移量,则结果将显着不同:

  • 输入:Thu, 02 Aug 2012 07:42:02
  • 输出:Thu, 02 Aug 2012

答案 3 :(得分:0)

.* greedy 因此在找到最后一个可能的四位\d{4}之前消耗尽可能多的字符。

在某些正则表达式引擎(例如perl)中,您可以添加?来指定非贪婪匹配:.*?\d{4},该匹配应与2012匹配。

答案 4 :(得分:0)

据说sybmol *“贪婪”。这意味着在强制匹配以下标记之前,它将匹配前一个字符的尽可能多的字符。 1525是最后一个可以满足\ d {4}的部分,所以。*抓住所有东西直到1525年。

?通常作为非贪婪的令牌。

答案 5 :(得分:0)

正则表达式引擎步骤:

matches                                | pattern | description
---------------------------------------+---------+-------------------------------
Thu, 02 Aug 2012 07:42:02 -1525 (CDT)  | .*      | match all possible characters
---------------------------------------+---------+-------------------------------
Thu, 02 Aug 2012 07:42:02 -1525 (CDT)  | \d{4}   | the RE doesn't find the 4 digits
---------------------------------------+---------+-------------------------------
Thu, 02 Aug 2012 07:42:02 -1525 (CDT   | \d{4}   | the RE backtracks char by char
---------------------------------------+---------+-------------------------------
Thu, 02 Aug 2012 07:42:02 -1525 (CD    | \d{4}   | to try to find the 4 digits
---------------------------------------+---------+-------------------------------
Thu, 02 Aug 2012 07:42:02 -1525 (C     | \d{4}   | no match
---------------------------------------+---------+-------------------------------

...

---------------------------------------+---------+-------------------------------
Thu, 02 Aug 2012 07:42:02 -1           | \d{4}   | no match
---------------------------------------+---------+-------------------------------
Thu, 02 Aug 2012 07:42:02 -1525        | \d{4}   | match
---------------------------------------+---------+-------------------------------