2012-06-21 3 views
7

Веб-сайт, на котором я работал, не будет сопоставлять данные с использованием шаблона регулярного выражения PHP (preg_match), который, кажется, работает везде, где я его тестировал. Этот шаблон:Являются ли эти шаблоны регулярных выражений разными?

<channel.*?>(.*?)</channel> 

Он сопоставляется с RSS-каналом с тегом канала.

Теперь сервер я работаю над будет производить только правильный результат, если изменить его на:

<channel.*?>(.*)?</channel> 

Моя регулярное выражение не является лучшим в мире, поэтому мне интересно, если кто-нибудь может сказать мне, если существует существенная разница между двумя шаблонами.

Небольшое примечание. Я понимаю, что было бы лучше использовать SimpleXML и т. Д., Но это регулярное выражение из предыдущего приложения и по разным причинам мне не разрешено изменять его.

Заранее благодарим за любые идеи.

+2

Является ' '' ваш PCRE разделителем? Если это так, модификатор 's' может или не может иметь значение (я не совсем уверен). – BoltClock

+0

Да '' 'является разделителем PCRE. Он использовался тем, кто первоначально написал код, обычно использует '#' или '~'. – Vunus

ответ

7

В заявлении (.*) говорится, что «выбор равен нулю или больше символов», а конечный ? делает его необязательным. В отличие от этого, (.*?) использует «ленивую звезду» (*?), которая сначала пытается полностью пропустить матч. Проверьте this для получения дополнительной информации.

Чтобы понять разницу между нормальной (жадной) звездой и ленивой звездой, посмотрите на следующий пример в PHP и обратите внимание, что жадная звезда делает наибольшее совпадение с шаблоном, которым она дается, а ленивая звезда «отказывается», как только он удовлетворил шаблон матча:

$inputs = array('axb' , 'axxxb' , 'axbxb' , 'axbxxxb'); 

// GREEDY STAR (NORMAL) 
foreach($inputs as $input) 
{ 
    preg_match('/a.*b/' , $input , $greedy); 
    $greedy_matches[] = $greedy[0]; 
} 

print "<pre>"; 
print_r($greedy_matches); 
print "</pre>"; 
/* 
Array 
(
    [0] => axb 
    [1] => axxxb 
    [2] => axbxb 
    [3] => axbxxxb 
) 
*/ 



// LAZY STAR 
foreach($inputs as $input) 
{ 
    preg_match('/a.*?b/' , $input , $lazy); 
    $lazy_matches[] = $lazy[0]; 
} 

print "<pre>"; 
print_r($lazy_matches); 
print "</pre>"; 
/* 
Array 
(
    [0] => axb 
    [1] => axxxb 
    [2] => axb 
    [3] => axb 
) 
*/ 
+0

Спасибо. Это помогло огромное количество (спасибо всем, кто ответил). Один маленький вопрос, который у меня есть, заключается в том, что код, который изначально был там (. *?) ', Кажется, работает повсюду, включая мой собственный сервер, но этот единственный сервер работает только с' (. *)? '. Это из-за «ленивой звезды», или это может быть что-то странное в этом сервере и это регулярное выражение? – Vunus

+0

Lazy star приходит от Perl, IIRC, так что может случиться так, что этот конкретный сервер использует библиотеку регулярных выражений, которая не имеет ленивой звезды. –

+0

Только что проверили и у него есть другая версия perl для моей версии, так что это будет лучшее объяснение, которое я слышал. Благодарю. – Vunus

-1

в регулярных выражениях * означает 0 или более раз - нет необходимости добавлять? после этого.

EDIT: как я теперь понимаю из комментариев, жадный делает разницу. Немного тест:

var_dump(preg_replace('/<channel.*?>(.*?).*<\/channel>/', '$1', '<channel>asd</channel>')); 
var_dump(preg_replace('/<channel.*?>(.*)?.*<\/channel>/', '$1', '<channel>asd</channel>')); 

Выходы

string(0) "" 
string(3) "asd" 

Как вы видите, я использую (.*?).* и (.*)?.*, так что жадные бы разницу. Но, поскольку это не одно и то же, в данном примере я не вижу, как это может повлиять.

+3

'*?' - нечеткий квантор с нулевым или большим числом. –

2

Я предполагаю, что вы на самом деле не хотите, чтобы оператор сам ленился. Леневый оператор, как правило, будет стараться соответствовать как можно меньше, что вполне может дать неожиданные результаты при работе с большим количеством данных, которые могут быть нерегулярными. Помещая вопросительный знак в конце жадной группы, вы добавляете необязательный матч к жадной группе, в отличие от того, чтобы сделать группу неживой (ленивой). Если вы хотите больше узнать о различии между жадностью и лень, проверьте это: http://www.regular-expressions.info/possessive.html.

0

Просьба привести пример текста, который вы пытаетесь сопоставить.

'<channel.*' will match anything starting with <channel 

'?>' will match a single character followed by > (so '1>', '2>', 'b>' etc) 

, если вы хотите, чтобы соответствовать все между просто использовать шаблон

'#<channel>(.*)</channel>#' 
Смежные вопросы