2013-03-19 5 views
3

У меня есть эта строка для проверки и не удается сделать это работает, как я хочу:preg_match выбрать матч первого селектора

<?php 
$string = '500 or fatal error ?'; 
$regex = '#(fatal|500)#'; 
if (preg_match($regex, $string, $return)) { 
    // Return 500 
    echo $return[1]; 
} 
?> 

Я хочу, чтобы мой сценарий, чтобы вернуться фатальным вместо 500, потому что это мой первый селектор. Возможно ли это?

Спасибо заранее, и извините за мой плохой английский.

P.S. : Может быть, мой титул не совсем ясен, но я не знаю, как объяснить это лучше. Если вы его найдете, измените его.

+0

Я не знаю, являются ли регулярные выражения подходящим инструментом здесь, поскольку они будут читать строки слева направо. –

+0

ну, первое совпадение было '500', совпадение начинается с начала строки, порядок в вашем регулярном выражении здесь не имеет значения –

+0

@MarkoD Можно ли изменить это поведение? –

ответ

2

Если вы хотите сделать это только с одним регулярным выражением, вы можете сделать это следующим образом:

$selectors = array('fatal', '500'); // Array of selectors (in priority order) 

$delimiter = '/'; 
$regex = $delimiter . '(' . implode('|', array_map('preg_quote', $selectors, array_fill(0, count($selectors), '/'))) . ')' . $delimiter; 
preg_match_all($regex, $string, $matches); 

Посмотрите, какой из селекторов мы нашли по порядку величины:

$found_selectors = array_flip($matches[1]); 
foreach($selectors as $selector) { 
    if(isset($found_selectors[$selector])) 
     return $selector; 
} 

Обратите внимание, что я перевернул $matches[1] массив, чтобы получить постоянное время поиска в массиве, вместо того, чтобы делать в array_search()/in_array(), который будет как сделать линейный поиск.

Вы можете видеть от this demo, что это производит fatal, учитывая вашу входную строку.

+0

Woah! Кажется, он работает точно так, как я хочу. Я смотрю на это, чтобы посмотреть, как это работает, спасибо большое! –

+0

Я как бы переглядывал объяснение, но '$ regex' просто формирует динамическое регулярное выражение так же, как и у вас, за исключением того, что я использую массив' $ selectors' и не забудьте правильно удалить все селекторы с помощью preg_quote() '. Затем вы возвращаете массив в '$ matches [1]' так же, как вы делали ранее, я просто переворачиваю массив и перебираю «селектора» (которые находятся в порядке приоритета), чтобы увидеть, какой из них (если есть) были найдены в строке. Первый, который будет найден, возвращается. – nickb

+0

Вот что я вижу. Потратьте время, чтобы все понять. Отличная логика, спасибо! –

2

Существует два вида двигателей регулярного выражения: text-directed engines и regex-directed двигателей.

РНР regex-directed двигатель, который всегда будет возвращать крайний левый матч, даже если «500» матч можно было бы узнать позже

Двигатель запускается с первого символа строки. Он будет попробует все возможные перестановки регулярного выражения на первом знаке . Только если все возможности были опробованы и найдены с ошибкой , двигатель продолжит работу со вторым символом в тексте. Опять же, он попробует все возможные перестановки регулярного выражения, точно в тот же заказ. В результате движок, ориентированный на регулярное выражение, будет вернуть самое левое совпадение.

Вы можете найти больше информации here

+0

Спасибо за объяснение.Я предполагаю, что невозможно заставить php вести себя как текстовый движок? –

+1

@Tyrius no вы не можете заставить его работать с текстовым движком – Anirudha

2

это не возможно, как вы намечаете, но другая реализация сделает работу

$string = '500 or fatal error'; 
$regexes = array('#\bfatal\b#', '#\b500\b#'); 

$match = null; 
foreach ($regexes as $re) 
    if (preg_match($re, $string, $match)) 
    break; 
# $match is null -> not found 
+1

Это также требует 'n' регулярных выражений и' n' оценок для селекторов 'n', где OP имеет 150, это может стать дорогостоящим. – nickb

+0

Я знаю это, но по своим собственным причинам я хотел выполнить поиск по регулярному выражению. Это кажется невозможным, поэтому я вернусь к этому пути. –

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