September 23

Regexp для парсинга URL по RFC

Не претендуя на истину в последней инстанции, однако, хотелось закрыть для себя этот вопрос на всегда. Частенько в скриптах posh\python и т.п. приходится на входе принимать в качестве параметра строку с URL и быть уверенным что это:

  1. точно URL
  2. иметь возможность легко получить его составляющие (схему\fqdn\query\etc)

Подсматривая в интернет, получилось написать вот такую "красивую" регулярку, которая входящую строку бъет на следующие группы:

  1. url (собственно если строка соответствует паттерну url - в этой группе будет отображаться полный url
  2. scheme - схема URL http:// | ftp:// | anycustomscheme://
  3. hostname - FQDN
  4. port
  5. path
  6. 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.

Спасибо что дочитали до конца, надеюсь это будет вам полезно.