PHP регулярное выражение с дополнительным символом в конце - PullRequest
0 голосов
/ 28 мая 2018

у меня есть следующая строка

https://www.example.com/int/de

и я хочу сопоставить код языка в конце URL, например, 'de', я делаю это с помощью этого регулярного выражения

/\..*\/.*\/([^\/?]*)\/?$/gi

Я также хотел бы получить тот же результат, если URL заканчивается косой чертой

Но с https://www.example.com/int/de/ я получаю только полное совпадение, но группа больше не соответствует 'de', хотя последняя косая черта необязательнав регулярном выражении

Может кто-то здесь моя ошибка?

Ответы [ 3 ]

0 голосов
/ 28 мая 2018

Ошибка не очевидна, но вполне обычна: «общий» шаблон сопоставления жадных точек сопровождается рядом необязательных подшаблонов (шаблонов, которые могут соответствовать пустой строке).

Шаблон \..*\/.*\/([^\/?]*)\/?$ соответствует следующему: \..* соответствует ., а затем любые 0+ символов, как можно больше, затем начинается обратное отслеживание для \/, чтобы соответствовать /, то естьсамый правый / в строке (последний), затем .*\/ снова сопоставляет любые 0+ символов как можно больше, а затем заставляет двигатель вернуться назад еще больше и вынуждает его отказаться от ранее найденного / и выполнить повторное сопоставление/, который стоит перед другим правым / в строке.Затем, наконец, наступает ([^\/?]*)\/?$, но предыдущий .*\/ уже сопоставлен в URL с / в конце, а индекс регулярного выражения находится в конце строки.Таким образом, поскольку ([^\/?]*) может соответствовать 0+ символов, отличных от ?, а / и \/? могут соответствовать 0 / символов, они оба соответствуют пустым строкам в конце строки, и $ вызывает егодень, и механизм регулярных выражений возвращает действительное совпадение с пустым значением в группе 1.

Чтобы избавиться от жадных точек, используйте

'~([^\/?]+)\/?$~'

См. демонстрационную версию regex

Подробности

  • ([^\/?]+) - Группа захвата 1: один или несколько символов, отличных от ? и /
  • \/? - 1 или 0 / символов
  • $ - в конце строки.
0 голосов
/ 28 мая 2018

В качестве альтернативы вы можете использовать parse_url с explode и 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>";
}

Thatдаст вам:

de
de
0 голосов
/ 28 мая 2018

Знак вопроса соответствует нулю или 1 символу .Вам нужно больше, чем один, чтобы соответствовать «де».Попробуйте использовать .* или .+ вместо ?.

Кстати, возможно, более поддерживаемым RegEx будет: /.*\/([^/]*)\/?$/gi

Это регулярное выражение говорит "соответствует чему угодно" (.*), за которым следует косая черта (\/), за которой следует символ, не являющийся косой чертой, ноль или более раз ([^/]*), за которым следует дополнительная косая черта (\/?), за которой следует конец текста($).Таким образом, все символы перед последней косой чертой и языковая часть будут сопоставлены в части регулярного выражения «сопоставить что угодно».Обратите внимание на круглые скобки вокруг части, которая представляет совпадение языка.

...