у меня есть следующая строка
https://www.example.com/int/de
и хотите сопоставить код языка в конце URL, например, ‘de’
я делаю это с этим регулярным выражением
/\..*\/.*\/([^\/?]*)\/?$/gi
Я также хотел бы получить тот же результат, если URL заканчивается косой чертой
Но с https://www.example.com/int/de/
я получаю только полное совпадение, но группа больше не соответствует ‘de’, хотя последний слеш необязательный в регулярном выражении
может кто то моя ошибка тут?
Ошибка не очевидна, но вполне обычна: «общий» шаблон сопоставления жадных точек сопровождается рядом необязательных подшаблонов (шаблонов, которые могут соответствовать пустой строке).
\..*\/.*\/([^\/?]*)\/?$
образец соответствует как это: \..*
соответствует .
и затем любые 0+ символов, как можно больше, затем начинается возврат \/
соответствовать /
это самый правый /
в строке (последней), затем .*\/
снова сопоставляет любые 0+ символов с максимально возможным количеством, а затем делает возврат двигателя еще дальше и вынуждает его отказаться от ранее найденного /
и заново сопоставить /
то есть до того, чтобы приспособиться к другому правому /
в строке. Затем, наконец, приходит ([^\/?]*)\/?$
, но предыдущий .*\/
уже сопоставлено в URL с /
в конце, и индекс регулярного выражения находится в конце строки. Итак, с ([^\/?]*)
может соответствовать 0+ символов кроме ?
а также /
а также \/?
может соответствовать 0 /
символы, они оба соответствуют пустым строкам в конце строки, и $
называет это днем, и механизм регулярных выражений возвращает действительное совпадение с пустым значением в группе 1.
Избавьтесь от жадных точек, используйте
'~([^\/?]+)\/?$~'
Увидеть regex demo
подробности
([^\/?]+)
— Группа захвата 1: один или несколько символов кроме ?
а также /
\/?
— 1 или 0 /
символы$
— в конце строки.В качестве альтернативы вы могли бы рассмотреть возможность использования parse_url с взрываться а также RTRIM чтобы получить только последнюю часть.
$strings = [
"https://www.example.com/int/de/",
"https://www.example.com/int/de"];
foreach ($strings as $string) {
$parts = explode("/", rtrim(parse_url($string, PHP_URL_PATH), '/'));
echo end($parts) . "<br>";
}
Это даст вам:
de
de
Знак вопроса соответствует нулю или 1 символу. Вам нужно более одного, чтобы соответствовать «де». Попробуйте использовать .*
или же .+
вместо ?
,
Кстати, вероятно, более регулярный RegEx будет:
/.*\/([^/]*)\/?$/gi
Это регулярное выражение говорит «соответствует чему угодно (.*
), после чего следует косая черта (\/
), за которым следует то, что не является косой чертой, ноль или более раз ([^/]*
), за которым следует дополнительная косая черта (\/?
), за которым следует конец текста ($
). Таким образом, все символы перед последней косой чертой и языковой частью будут сопоставлены в части регулярного выражения «сопоставить что угодно». Обратите внимание на круглые скобки вокруг части, которая представляет соответствие языка.