2016-08-03 65 views
2

我需要比賽datastamp與ZEROFILL多種變化,而不會等

在一天ZEROFILL模式相匹配的各種日戳的文本字符串/月

$date_day_pattern = '0[1-9]|[12][0-9]|3[01]'; 
$date_month_pattern = '0[1-9]|1[0-2]'; 
$date_year_pattern = '[12][0-9]|20[12][0-9]'; 

$date_pattern = "(?<!\d)($date_day_pattern)[^\d]?($date_month_pattern)[^\d]?($date_year_pattern)(?!\d)"; 
preg_match("/$date_pattern/m", $input, $matches); 

匹配時,該工作
01-05-2015 
01-05-15 
01052015 
010515 

但我還需要匹配日期/時間沒有zerofill的日期戳。但隨後的郵戳必須有日,月,年

1-5-2015 

模式必須比賽

152015 

回答

2

你可以添加額外的替代前兩個表達式之間的分隔符:

  • 當天模式:[1-9](?=\D)
  • 對於月份模式RN:(?<=\D)[1-9](?=\D)

這將成爲:

$date_day_pattern = '0[1-9]|[12][0-9]|3[01]|[1-9](?=\D)'; 
$date_month_pattern = '0[1-9]|1[0-2]|(?<=\D)[1-9](?=\D)'; 
$date_year_pattern = '[12][0-9]|20[12][0-9]'; 

$date_pattern = "(?<!\d)($date_day_pattern)\D?($date_month_pattern)\D?($date_year_pattern)(?!\d)"; 

上面甚至會匹配諸如怪異,但無歧義的字符串:

2-0116 

...但它不會允許:

201-16 

請注意,\D相當於[^\d]

+0

所以'(?=)'是某種先行的? – clarkk

+0

和'(?<=)'後面的一樣? – clarkk

+0

事實上,你固定它:積極向前看,往後看。 – trincot

1

您可以使用conditional subpattern feature,即如果前導0匹配,則使分隔符可選,否則使其成爲強制性的。

$date_pattern = 
'(?<!\d)((0)?[1-9]|[12][0-9]|3[01])(?(2)\D?|\D)(0?[1-9]|1[0-2])(?(2)\D?|\D)([12][0-9]|20[12][0-9])(?!\d)'; 
  • 可選捕獲組2是(0)?
  • (?(2)\D?|\D)使得\D可選如果組#2匹配否則\D(非數字)是必需的。

RegEx Demo