使用preg_match捕获PHP中方括号之间的日期和时间

时间:2016-12-08 04:02:57

标签: php regex datetime preg-match

我需要一些方法来捕捉方括号之间的日期和时间。所以对于以下字符串:

$str= '10.1.1.107 - - [27/Oct/2016:06:40:58 +0000] "GET /advise/asi/3571502300/sky/2/con/113 HTTP/1.1"';

我想要获得advisecon,如下所示:

preg_match("/advise\/([a-zA-Z0-9\-]+)\/sky\/2\/.*con\/([0-9]+)/", $str, $matches);

该函数返回以下$matches

Array ( 
 [0] => 
  array(2) {
   [0]=>
    "3571502300"
   [1]=>
    "113"
 }
)

然后我想在方括号之间得到日期和时间,我有以下正则表达式:

/\[([0[1-9]|[1-2][0-9]|3[0-1]\/Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec\/20\d\d:\d{2}:\d{2}:\d{2}\+0000)]\]\/advise\/([a-zA-Z0-9\-]+)\/sky\/2\/.* con\/([0-9]+)/ 

captures nothing

我的正则表达式错了吗?

我得到一个这样的数组:

Array ( 
 [0] => 
  array(3) {
   [0]=>
    27/Oct/2016:06:40:58 +0000 
   [1]=>
    "3571502300"
   [2]=> 
    "113"
 }
)

2 个答案:

答案 0 :(得分:1)

$re = '/\[(?P<dt>\d\d\/[A-Z][a-z]{2}\/\d{4}(?:\:\d\d){3} \+\d{4})\] ' .
  '"[A-Z]{3,4} \/advise\/asi\/(?P<asi>\d+)\/sky\/\d+\/con\/(?P<con>\d+)/';

preg_match($re, $str, $m);
var_dump($m['dt'], $m['asi'], $m['con']);
// or, if your prefer numeric indices:
//var_dump($m[1], $m[2], $m[3]);

输出

string(26) "27/Oct/2016:06:40:58 +0000"
string(10) "3571502300"
string(3) "113"

<强>描述

使用以下格式的名称subpatterns捕获值:

(?P<name>pattern)

其中name是匹配数组中的键名。

(?:\:\d\d){3}non-capturing group年后的部分set of characters(特别是:06:40:58)。

其余的很简单。

正则表达式中的错误

请注意,在上面的示例代码中,方括号使用反斜杠进行转义:\[\],因为在正则表达式中它们表示Microsoft Portable Executable and Common Object File Format Specification。您没有转义方括号,因此两者之间的字符被解释为一组字符。

部分sky\/2\/.* con\/错误,因为原始字符串在con/之前不包含空格。

您已对时区偏移(\+0000)进行了硬编码。虽然主机上的时区不太可能发生变化,但仍有可能。因此,最好以更具遗传性的形式编写,例如\+\d{4}

答案 1 :(得分:1)

您需要对替代版本进行分组,否则or会影响整个正则表达式。

例如:

^12|34$

允许1234

^1(2|3)4$

允许124134

你的字符串在时区偏移和秒之间也有一个空格,所以你需要按字面意思添加(或者你可以使用\h元字符)。

演示:https://regex101.com/r/ykuAP9/3

所以正则表达式应该是:

~\[((?:[0[1-9]|[1-2][0-9]|3[0-1])/(?:Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)/20\d\d:\d{2}:\d{2}:\d{2} \+0000)\]~