我想从日期时间偏移值中去掉(CDT)
。我写了下面的简单的正则表达式来这样做,它的工作原来是预期的,但写完后我仍然想知道为什么它可以工作。为什么2012年的结果不会停止?为什么这个正则表达式工作?
原始字符串:"Thu, 02 Aug 2012 07:42:02 -1525 (CDT)"
正则表达式:.*\d{4}
结果:"Thu, 02 Aug 2012 07:42:02 -1525"
我想从日期时间偏移值中去掉(CDT)
。我写了下面的简单的正则表达式来这样做,它的工作原来是预期的,但写完后我仍然想知道为什么它可以工作。为什么2012年的结果不会停止?为什么这个正则表达式工作?
原始字符串:"Thu, 02 Aug 2012 07:42:02 -1525 (CDT)"
正则表达式:.*\d{4}
结果:"Thu, 02 Aug 2012 07:42:02 -1525"
的量词*
是贪婪的。这意味着它会尽可能匹配。
这就是为什么\d{4}
匹配1525
和.*
匹配之前的字符。
如果您使用惰性量词*?
,那么在尝试更长的序列之前,它将首先与最少的字符数匹配。在这种情况下,它会让\d{4}
与2012
匹配。
图案.*\d{4}
匹配后跟4个数字的零个或多个字符(贪婪地)的任何序列。
它的工作原理是匹配所有字符串中的最后四位数字(1525
),并忽略字符串的其余部分。
请注意您的图案有点危险。如果输入缺少的时区偏移,其结果必然是显著不同:
Thu, 02 Aug 2012 07:42:02
Thu, 02 Aug 2012
.*
是贪婪因此它会在查找最后四位数字之前消耗尽可能多的字符\d{4}
。
在一些正则表达式引擎(如Perl),您可以添加?
指定非贪婪比赛:.*?\d{4}
,这应该与2012年
的sybmol *被说成是“贪婪”。这意味着在强制匹配下面的标记之前,它将匹配前面字符的尽可能多的字符。 1525是可以满足\ d {4}的最后一个可能部分,所以。*将所有东西都抓到1525.
?通常作为一个非贪婪的标志。
它的工作原理是.*
是greedy。
这意味着.*
会在做其他事情之前尽可能匹配。
当正则表达式的应用,.*
整个事情相匹配,因为它是贪婪:
星期四,2012年8月2日7时42分02秒-1525(CDT)
然后尝试以匹配\d{4}
,但不幸的是,它不匹配任何东西,因为它在最后。因此,正则表达式(在.*
部分)将回溯(回去给回什么是先前已经匹配)一次,每次一个字符,并检查\d{4}
:
星期四,2012年8月2日07 :42:02 -1525(CDT)[无匹配]
星期四,2012年8月2日7时42分02秒-1525(CD T)[无匹配]
星期四,2012年8月2日07:42:02 -1525(C DT)[No ma TCH]
星期四,2012年8月2日7时42分02秒-1525( CDT)[无匹配]
星期四,2012年8月2日7时42分02秒-1525(CDT)[不比赛]
星期四,2012年8月2日7时42分02秒-1525(CDT)没有匹配]
...
星期四,2012年8月2日7时42分02秒 - 1525(CDT)
在这一点上,它能够匹配\d{4}
,所以这就是它会做:
星期四,2012年8月2日7时42分02秒-1525( CDT)
而且由于正则表达式中没有别的东西,所以会在这里结束。
正则表达式引擎步骤:
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
---------------------------------------+---------+-------------------------------