Регекс не соответствует, жадность
Я пытаюсь сопоставить две части в строке с регулярным выражением в PHP. Есть проблема с жадностью, я думаю. Я хотел бы, чтобы первое регулярное выражение (см. Комментарий) дало мне первые два захвата, как второе регулярное выражение, но все еще захватывало обе строки. Что я делаю неправильно?
Я пытаюсь получить +123
(если cd:
существует, как в первой строке) и 456
,
<?php
$data[] = 'longstring start waste cd:+123yz456z longstring';
$data[] = 'longstring start waste +yz456z longstring';
$regexs[] = '/start[^z]*?(cd:([^y]+)y)?[^z]*z([^z]*)z/'; // first
$regexs[] = '/start[^z]*?(cd:([^y]+)y)[^z]*z([^z]*)z/'; // second
foreach ($regexs as $regex) {
foreach ($data as $string) {
if (preg_match($regex, $string, $match)) {
echo "Tried '$regex' on '$string' and got " . implode(',', array_split($match, 1));
echo "\n";
}
}
}
?>
Выход:
Tried '/start[^z]*?(cd:([^y]+)y)?[^z]*z([^z]*)z/' on 'longstring start waste cd:+123yz456z longstring' and got ,,456
Tried '/start[^z]*?(cd:([^y]+)y)?[^z]*z([^z]*)z/' on 'longstring start waste +yz456z longstring' and got ,,456
Tried '/start[^z]*?(cd:([^y]+)y)[^z]*z([^z]*)z/' on 'longstring start waste cd:+123yz456z longstring' and got cd:+123y,+123,456
Там нет четвертой линии с cd:
нет во второй строке.
Ожидаемый результат (так как я не эксперт), где первая строка отличается от фактического результата:
Tried '/start[^z]*?(cd:([^y]+)y)?[^z]*z([^z]*)z/' on 'longstring start waste cd:+123yz456z longstring' and got cd:+123y,+123,456
Tried '/start[^z]*?(cd:([^y]+)y)?[^z]*z([^z]*)z/' on 'longstring start waste +yz456z longstring' and got ,,456
Tried '/start[^z]*?(cd:([^y]+)y)[^z]*z([^z]*)z/' on 'longstring start waste cd:+123yz456z longstring' and got cd:+123y,+123,456
1 ответ
Итак, вы хотите захватить +123
если есть cd:
, и всегда 456
? Вот как бы я это сделал:
$data[] = 'longstring start waste cd:+123yz456z longstring';
$data[] = 'longstring start waste +yz456z longstring';
$regexs[] = '/start.+?(?:cd:(.+?)y)?.*?z(.+?)z/';
С либеральным употреблением не жадных (?
) множители, вы можете заставить его делать именно то, что вы хотите.
Также обратите внимание на (?:)
группа без захвата. Они очень полезны.
РЕДАКТИРОВАТЬ Очевидно, что это не работает, давайте попробуем другой подход, с группой "или / или":
$regexs[] = '/start.+?(?:cd:(.+?)yz(.+?)z|\+yz(.+?)z)/';