Парсинг URL регулярками PHP

200
24 апреля 2018, 01:44

Товарищи, пишу парсер ссылок

"https://domain.ru:8080/folder/subfolder/../././?var1=val1&var2=val2"
"https://http.google.com/folder/././?var1=val1&var2=val2",
"ftp://mail.ru/?hello=world&url=https://http.google.com/folder//././?var1=val1&var2=val2",

что нужно исправить в регулярке что бы она результат был корректен при отсутствие любой части ссылки ( если нет протокола то все ок если нет домена то тоже все ок, проблемы с путем - регулярка считает то что написано в параметрах за путь : иными словами что нужно исправить что бы регулярка не лезла в параметры)

вот моя регулярка :

$_re = 
    "~^
        (?:(?<protocol>http|https|ftp):\\/\\/)?                  
        (?<domain_name>
            (?<domain_2_lvl>[a-z0-9\.]+)
            \.
            (?<zone>[a-z]{2,4})
            :?(?<port>[0-9]{4})?
        )?
        |(?<raw_folder> ((?<=\/)([a-z.]+)(?=\/)))
        |(?<script>script.php)?
        |\?
        |(?<key>[a-z0-9?\/_]+)=(?<value>[a-z0-9?\/_]+)?
    ~ix"
preg_match_all($_re, $__url, $matches);
Answer 1

Можно добавить альтернативу | и "просмотры" вперёд и назад, а пустые элементы в массиве отфильтровать:

$url = 'https://domain.ru:8080/folder/subfolder/../././?var1=val1&var2=val2';
$patt = '~^
    (?:(?<protocol>(?:ht|f)tps?)://)?
    (?<domain_name>
        (?<domain_2_lvl>[\pL\d.-]+)?
        \.
        (?<zone>\pL{2,4})
        (?::(?<port>\d{4}))?
    )?
    | (?<raw_folder>(?<=/)[\pL.]+(?=/))
~ix';
preg_match_all($patt, $url, $matches);
$matches = array_map('array_filter', $matches);

Результат:

var_dump(
    $matches['protocol'],     // https
    $matches['domain_name'],  // domain.ru:8080
    $matches['domain_2_lvl'], // domain
    $matches['zone'],         // ru
    $matches['port'],         // 8080
    $matches['raw_folder']    /* array (size=5)
        1 => string 'folder' (length=6)
        2 => string 'subfolder' (length=9)
        3 => string '..' (length=2)
        4 => string '.' (length=1)
        5 => string '.' (length=1)
    */
);
Answer 2

Совместными усилиями получилось

 $_re = 
    "~^
    (?:(?<protocol>http|https|ftp):\\/\\/)?                  
    (?<domain_name>
        (?<domain_2_lvl>[a-z0-9\.]+)
        \.
        (?<zone>[a-z]{2,4})
        :?(?<port>[0-9]{4})?
    )?
    |(?<raw_folder> ((?<=\/)([a-z.]+)(?=\/)))
    |(?<script>script.php)?
    |(?<key>[a-z0-9\/_]+)=(?<value>[a-z0-9?\/_:.]+)
    ~ix";

Подкорректируйте, если я ошибаюсь

READ ALSO
PhP массивы, выводит значение как &ldquo;..&rdquo;

PhP массивы, выводит значение как “..”

Люди добрые! Почему первое значение массива PHP выводится как ""? Нет никаких идей , всё перепробовала

196
PHP и MySQL. Запрос в цикле

PHP и MySQL. Запрос в цикле

Доброго времени суток! Имеется таблица со снятыми показаниями портативной метеостанции (одна строка, новые значения заменяют предыдущие,...

186
Как сделать кнопку выбора и загрузки файла одним кликом на ajax, без перезагрузки сайта?

Как сделать кнопку выбора и загрузки файла одним кликом на ajax, без перезагрузки сайта?

Вот небольшой пример кода, где две кнопки: "Выбрать файл" и "Загрузить"После загрузки файла сайт перезагружается

182
В чем смысл миграций

В чем смысл миграций

Здравствуйте!

174