2016-12-08 3 views
0

Мне нужен способ захвата даты и времени между квадратными скобками. Так что для следующей строки:Захват даты и времени между квадратными скобками в PHP с использованием 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"'; 

Я Тринг, чтобы получить advise и con следующим образом:

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" 
} 
) 

ответ

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 для деталей после года (в частности, :06:40:58).

Остальное простое.

ошибки в регулярных выражениях

Обратите внимание, что в вышеприведенном примере кода в квадратных скобках с обратной косой чертой: \[, \], так как в регулярных выражениях они означают set of characters. Вы не избежали квадратных скобок, поэтому символы между ними интерпретируются как набор символов.

Часть sky\/2\/.* con\/ неверна, поскольку исходная строка не содержит пробелов до con/.

У вас есть жестко закодированное смещение часового пояса (\+0000). Хотя маловероятно, что часовой пояс изменится на вашем хосте, это все еще возможно. Поэтому лучше записать его в более генетической форме, например. \+\d{4}.

1

Вам нужно сгруппировать свои альтернативные версии, иначе or влияет на все регулярное выражение.

Например:

^12|34$ 

Позволяет 12 или 34 но

^1(2|3)4$ 

Позволяет 124 или 134.

Ваша строка также имеет пробел между смещением временной зоны и секундами, поэтому вам нужно добавить это буквально (или вы можете использовать метасимвол \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)\]~ 
+0

Формат DATETIME вы упомянули правильно –

Смежные вопросы