Regexp для парсинга URL по RFC
Не претендуя на истину в последней инстанции, однако, хотелось закрыть для себя этот вопрос на всегда. Частенько в скриптах posh\python и т.п. приходится на входе принимать в качестве параметра строку с URL и быть уверенным что это:
Подсматривая в интернет, получилось написать вот такую "красивую" регулярку, которая входящую строку бъет на следующие группы:
- url (собственно если строка соответствует паттерну url - в этой группе будет отображаться полный url
- scheme - схема URL http:// | ftp:// | anycustomscheme://
- hostname - FQDN
- port
- path
- query
Как работает этот regexp вы можете увидеть ниже
(?<url>(?:(?<scheme>[a-zA-Z]+:\/\/)?(?<hostname>(?:[-a-zA-Z0-9@%_\+~#=]{1,256}\.){1,256}(?:[-a-zA-Z0-9@%_\+~#=]{1,256})))(?::(?<port>[[:digit:]]+))?(?<path>(?:\/[-a-zA-Z0-9!amp;'()*+,\\\/:;=@\[\]._~%]*)*)(?<query>(?:(?:\#|\?)[-a-zA-Z0-9!amp;'()*+,\\\/:;=@\[\]._~]*)*))
На Python именованные группы нужно обозначать через символ P, поэтому для Python regex будет выглядеть чуть иначе:
(?P<url>(?:(?P<scheme>[a-zA-Z]+:\/\/)?(?P<hostname>(?:[-a-zA-Z0-9@%_\+~#=]{1,256}\.){1,256}(?:[-a-zA-Z0-9@%_\+~#=]{1,256})))(?::(?P<port>[[:digit:]]+))?(?P<path>(?:\/[-a-zA-Z0-9!amp;'()*+,\\\/:;=@\[\]._~%]*)*)(?P<query>(?:(?:\#|\?)[-a-zA-Z0-9!amp;'()*+,\\\/:;=@\[\]._~]*)*))
Ну и пример кода на Powershell:
$URL = "https://vcloud.lab.ihumster.ru/api/query?type=adminOrgVdcStorageProfile" $URL -match "(?<url>(?:(?<scheme>[a-zA-Z]+:\/\/)?(?<hostname>(?:[-a-zA-Z0-9@%_\+~#=]{1,256}\.){1,256}(?:[-a-zA-Z0-9@%_\+~#=]{1,256})))(?::(?<port>[[:digit:]]+))?(?<path>(?:\/[-a-zA-Z0-9!amp;'()*+,\\\/:;=@\[\]._~%]*)*)(?<query>(?:(?:\#|\?)[-a-zA-Z0-9!amp;'()*+,\\\/:;=@\[\]._~]*)*))" $Matches True Name Value ---- ----- path /api/query hostname vcloud.lab.ihumster.ru url https://vcloud.lab.ihumster.ru/api/query?type=adminOrgVdcStorageProfile scheme https:// query ?type=adminOrgVdcStorageProfile 0 https://vcloud.lab.ihumster.ru/api/query?type=adminOrgVdcStorageProfile
Операнд -math возвращает boolean результат соответствия строки в $URL нашему регулярному выражению и если он True, то автопеременная $Matches будет содержать key-value словарь в котором ключами будут имена групп с соответствующими values.
Спасибо что дочитали до конца, надеюсь это будет вам полезно.