Получение частей URL-адреса (Regex)

Учитывая URL-адрес (одна строка):
http://test.example.com/dir/subdir/file.html

Как с помощью регулярных выражений извлечь следующие части:

  1. Поддомен (тест)
  2. Домен (example.com)
  3. Путь без файла (/ dir / subdir /)
  4. Файл (file.html)
  5. Путь к файлу (/dir/subdir/file.html)
  6. URL без пути (http://test.example.com)
  7. (добавьте любое другое, что, по вашему мнению, будет полезно)

Регулярное выражение должно работать правильно, даже если я введу следующий URL:

http://example.example.com/example/example/example.html

person pek    schedule 26.08.2008    source источник
comment
Это не прямой ответ, но в большинстве веб-библиотек есть функция, которая выполняет эту задачу. Функцию часто называют чем-то похожим на CrackUrl. Если такая функция существует, используйте ее, она почти гарантированно будет более надежной и более эффективной, чем любой код, созданный вручную.   -  person Konrad Rudolph    schedule 26.08.2008
comment
Пожалуйста, объясните нам, почему это нужно делать с помощью регулярного выражения. Если это домашнее задание, скажите это, потому что это ваше ограничение. В противном случае есть лучшие решения для конкретного языка, чем использование регулярного выражения.   -  person Andy Lester    schedule 17.09.2010
comment
Ссылки на первый и последний образцы не работают.   -  person the Tin Man    schedule 17.01.2011
comment
Здесь вы можете узнать, как извлечь схему, домен, TLD, порт и путь запроса: stackoverflow.com/questions/9760588/   -  person Paolo Rovelli    schedule 12.08.2015


Ответы (28)


Одно регулярное выражение для синтаксического анализа и разбиения полного URL-адреса, включая параметры запроса и якоря, например

https://www.google.com/dir/1/2/search.html?arg=0-a&arg1=1-b&arg3-c#hash

^((http[s]?|ftp):\/)?\/?([^:\/\s]+)((\/\w+)*\/)([\w\-\.]+[^#?\s]+)(.*)?(#[\w\-]+)?$

Позиции RexEx:

url: RegExp ['$ &'],

протокол: RegExp. $ 2,

хост: RegExp. $ 3,

путь: RegExp. $ 4,

файл: RegExp. $ 6,

запрос: RegExp. $ 7,

хеш: RegExp. $ 8

затем вы могли бы довольно легко продолжить синтаксический анализ хоста (с разделителями ".").

Что я сделал бы, так это использовал бы что-то вроде этого:

/*
    ^(.*:)//([A-Za-z0-9\-\.]+)(:[0-9]+)?(.*)$
*/
proto $1
host $2
port $3
the-rest $4

дальнейший синтаксический анализ «остального», чтобы быть как можно более конкретным. Делать это в одном регулярном выражении - это немного безумие.

person Community    schedule 26.08.2008
comment
Ссылка codenippets.joyent.com/posts/show/523 не работает с 20 октября '10 - person W3Max; 20.10.2010
comment
Проблема в этой части: (.*)? Поскольку звезда Клини уже принимает 0 или более, часть ? (0 или 1) сбивает ее с толку. Я исправил это, изменив (.*)? на (.+)?. Вы также можете просто удалить ? - person rossipedia; 26.10.2010
comment
Хороший улов, Брайан. Я не собираюсь редактировать ответ, так как я процитировал его из (теперь уже удаленной) ссылки, но проголосовал за ваш комментарий, чтобы разъяснение было более заметным. - person hometoast; 28.10.2010
comment
Перечисленное регулярное выражение является очень хорошим ответом, но не совсем правильным, в нем отсутствует один / из протокола и происходит превышение соответствия строки запроса и сбор хэша в элементе 7 ... это устраняет эти две проблемы - ^ ((http [s]? | Ftp ): \ / \ /)? \ /? ([^: \ / \ s] +) ((\ / \ w +) * \ /) ([\ w \ - \.] + [^ #? \ s] +) (. *?)? (# [\ w \ -] +)? $ - person Dve; 23.06.2011
comment
Привет, Две, я немного улучшил его, чтобы извлекать example.com из URL-адресов, таких как http://www.example.com:8080/.... Вот и: ^((http[s]?|ftp):\/\/)?\/?([^\/\.]+\.)*?([^\/\.]+\.[^:\/\s\.]{2,3}(\.[^:\/\s\.]{2,3})?(:\d+)?)($|\/)([^#?\s]+)?(.*?)?(#[\w\-]+)?$ - person mnacos; 28.02.2012
comment
и доказательство того, что ни одно регулярное выражение не является идеальным, вот одно немедленное исправление: ^((http[s]?|ftp):\/\/)?\/?([^\/\.]+\.)*?([^\/\.]+\.[^:\/\s\.]{2,3}(\.[^:\/\s\.]{2,3})?)(:\d+)?($|\/)([^#?\s]+)?(.*?)?(#[\w\-]+)?$ - person mnacos; 28.02.2012
comment
Я что-то упускаю? Это не соответствует ни одному URL-адресу, который не заканчивается косой чертой, например www.google.com, что кажется большой проблемой. - person roryok; 09.07.2012
comment
как вы понимаете, в регулярном выражении есть множество исправлений и вариаций. Комментарии mnacos кое-что исправляют. - person hometoast; 09.07.2012
comment
похоже, что ни один из них не работает правильно. Например, для хоста google.co.uk он возвращает co.uk. Похоже, что единственный способ сделать это - составить исчерпывающий список всех ccTLD в мире, включая административные подразделения (.com.gt, ac.uk и т. Д.), И работать в обратном направлении. - person roryok; 10.07.2012
comment
попробуйте это url=/^(?:(.*?):\/\/?)?\/?(?:[^\/\.]+\.)*?([^\/\.]+)\.?([^\/]*)(?:([^?]*)?(?:\?([^#]*))?)?(.*)?/ url.exec("any_protocol://sbd.domain.foo.gooo/path/to/file.php?a=1&b=2#hash") ------------------------ - person bortunac; 04.02.2015
comment
@mnacos, возможно, вы допустили хитрую ошибку в своем комментарии от 28 февраля 2012, 14:41. Когда вы скопируете свое регулярное выражение в vim, вы заметите, что оно содержит символы Юникода, такие как <200c><200b>, или это было сделано намеренно. - person Egel; 11.05.2016
comment
что, если я написал https? вместо http[s]?? - person Manticore; 26.07.2016
comment
Я изменил это регулярное выражение, чтобы идентифицировать все части URL-адреса (улучшенная версия) - код на Python ^((?P<scheme>[^:/?#]+):(?=//))?(//)?(((?P<login>[^:]+)(?::(?P<password>[^@]+)?)?@)?(?P<host>[^@/?#:]*)(?::(?P<port>\d+)?)?)?(?P<path>[^?#]*)(\?(?P<query>[^#]*))?(#(?P<fragment>.*))? code Вы показываете этот код в действии на pythex .org - person arannasousa; 09.08.2017
comment
@DrunkenPoney Вы не сказали почему вы редактировали регулярное выражение, и вы не оставили поясняющий комментарий. - person jpaugh; 05.02.2018
comment
Регулярное выражение не работает, если длина пути составляет всего один символ, например https://example.com/a?foo=bar не соответствует. Я не понимаю, почему существует это ограничение (соответствующая часть регулярного выражения ([\w\-\.]+[^#?\s]+)) - person Arno Hilke; 26.11.2019
comment
Я ненавижу публиковать ссылки на меня, но не все могут использовать регулярное выражение python, а ранее опубликованные регулярные выражения не зависят от языка или с треском терпят неудачу с URL-адресами, такими как mailto: [email protected], или полностью аутентифицированными URL-адресами, или которые не имеют косая черта в конце или содержать порты, например jim: [email protected]: 8080. Этот справляется со всем, что я мог ему сказать. ^(([^@:\/\s]+):\/?)?\/?(([^@:\/\s]+)(:([^@:\/\s]+))?@)?([^@:\/\s]+)(:(\d+))?(((\/\w+)*\/)([\w\-\.]+[^#?\s]*)?(.*)?(#[\w\-]+)?)?$ - person Jeremy; 11.03.2020

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

var a = document.createElement('a');
a.href = 'http://www.example.com:123/foo/bar.html?fox=trot#foo';

['href','protocol','host','hostname','port','pathname','search','hash'].forEach(function(k) {
    console.log(k+':', a[k]);
});

/*//Output:
href: http://www.example.com:123/foo/bar.html?fox=trot#foo
protocol: http:
host: www.example.com:123
hostname: www.example.com
port: 123
pathname: /foo/bar.html
search: ?fox=trot
hash: #foo
*/
person Rob    schedule 18.09.2012
comment
Учитывая, что исходный вопрос был помечен как языково-агностический, что это за язык? - person MarkHu; 01.03.2014
comment
обратите внимание, что это решение требует наличия префикса протокола, например http://, для правильного отображения свойств протокола, хоста и имени хоста. В противном случае начало URL-адреса до первой косой черты переходит в свойство протокола. - person Oleksii Aza; 10.06.2014
comment
Я считаю это хоть и простым, но гораздо медленнее, чем парсинг RegEx. - person demisx; 10.02.2015
comment
Поддерживаются ли все браузеры? - person sean; 13.05.2015
comment
Если мы пойдем этим путем, вы также можете сделать var url = new URL(someUrl) - person gman; 18.10.2015
comment
@MarkHu .forEach и console.log подразумевают, что его JavaScript. К сожалению, не зависит от языка. - person A User; 22.12.2015
comment
@AUser какая разница? :) - person Rathma; 19.10.2016
comment
@gman: К сожалению, конструктор URL () не реализован в IE11 и Edge. - person Artif3x; 25.09.2017

Я опоздал на вечеринку на несколько лет, но удивлен, что никто не упомянул, что в спецификации Uniform Resource Identifier есть раздел, посвященный синтаксическому анализу URI с регулярным выражением. Регулярное выражение, написанное Бернерсом-Ли и др., Выглядит следующим образом:

^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?
 12            3  4          5       6  7        8 9

Цифры во второй строке выше предназначены только для облегчения чтения; они указывают ориентиры для каждого подвыражения (т. е. каждую парную скобку). Мы ссылаемся на значение, соответствующее подвыражению, как $. Например, сопоставление приведенного выше выражения с

http://www.ics.uci.edu/pub/ietf/uri/#Related

приводит к следующим совпадениям подвыражения:

$1 = http:
$2 = http
$3 = //www.ics.uci.edu
$4 = www.ics.uci.edu
$5 = /pub/ietf/uri/
$6 = <undefined>
$7 = <undefined>
$8 = #Related
$9 = Related

Как бы то ни было, я обнаружил, что мне нужно избегать косых черт в JavaScript:

^(([^:\/?#]+):)?(\/\/([^\/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?

person gwg    schedule 05.11.2014
comment
отличный ответ! Выбор чего-то из RFC наверняка никогда не повредит неправильный поступок. - person frankster; 29.01.2016
comment
это не анализирует параметры запроса - person Rémy DAVID; 25.11.2016
comment
Это лучший афаикт. В частности, это решает две проблемы, которые я видел с другими: 1: это правильно работает с другими протоколами, такими как ftp:// и mailto://. 2: это правильно работает с username и password. Эти необязательные поля разделены двоеточием, как и имя хоста и порт, и это вызовет сбой в большинстве других регулярных выражений, которые я видел. @ RémyDAVID Строка запроса также не анализируется нормально location объектом браузера. Если вам нужно проанализировать строку запроса, посмотрите для этого мою крошечную библиотеку: uqs. - person Stijn de Witt; 26.01.2017
comment
Этот ответ заслуживает большего количества голосов, потому что он охватывает практически все протоколы. - person Tianzhen Lin; 30.01.2017
comment
Он ломается, когда подразумевается протокол HTTP с именем пользователя / паролем (я признаю эзотерический и технически недопустимый синтаксис): например, user:[email protected] - RFC 3986 говорит: A path segment that contains a colon character (e.g., "this:that") cannot be used as the first segment of a relative-path reference, as it would be mistaken for a scheme name. Such a segment must be preceded by a dot-segment (e.g., "./this:that") to make a relative- path reference. - person Matt Chambers; 07.04.2017
comment
Это не отделяет имя домена от порта, как в http://www.ics.uci.edu:9000/pub/ietf/uri/#Related. - person Fernando Correia; 10.06.2017

Я обнаружил, что ответ, получивший наибольшее количество голосов (ответ домашнего тоста), не работает для меня идеально. Две проблемы:

  1. Он не может обрабатывать номер порта.
  2. Хеш-часть сломана.

Ниже приводится модифицированная версия:

^((http[s]?|ftp):\/)?\/?([^:\/\s]+)(:([^\/]*))?((\/\w+)*\/)([\w\-\.]+[^#?\s]+)(\?([^#]*))?(#(.*))?$

Расположение деталей следующее:

int SCHEMA = 2, DOMAIN = 3, PORT = 5, PATH = 6, FILE = 8, QUERYSTRING = 9, HASH = 12

Редактировать опубликовано анонимным пользователем:

function getFileName(path) {
    return path.match(/^((http[s]?|ftp):\/)?\/?([^:\/\s]+)(:([^\/]*))?((\/[\w\/-]+)*\/)([\w\-\.]+[^#?\s]+)(\?([^#]*))?(#(.*))?$/i)[8];
}
person mingfai    schedule 21.11.2008
comment
Помните, что это не сработает, если URL-адрес не имеет пути после домена - например, http://www.example.com или если путь состоит из одного символа, например http://www.example.com/a. - person Fernando Correia; 11.06.2017

Мне нужно было регулярное выражение для соответствия всем URL-адресам, и я сделал это:

/(?:([^\:]*)\:\/\/)?(?:([^\:\@]*)(?:\:([^\@]*))?\@)?(?:([^\/\:]*)\.(?=[^\.\/\:]*\.[^\.\/\:]*))?([^\.\/\:]*)(?:\.([^\/\.\:]*))?(?:\:([0-9]*))?(\/[^\?#]*(?=.*?\/)\/)?([^\?#]*)?(?:\?([^#]*))?(?:#(.*))?/

Он соответствует всем URL-адресам, любому протоколу, даже таким URL-адресам, как

ftp://user:[email protected]:8080/dir1/dir2/file.php?param1=value1#hashtag

Результат (в JavaScript) выглядит так:

["ftp", "user", "pass", "www.cs", "server", "com", "8080", "/dir1/dir2/", "file.php", "param1=value1", "hashtag"]

URL как

mailto://[email protected]

выглядит так:

["mailto", "admin", undefined, "www.cs", "server", "com", undefined, undefined, undefined, undefined, undefined] 
person baadf00d    schedule 15.08.2012
comment
Если вы хотите сопоставить весь домен / IP-адрес (не разделенный точками), используйте этот: /(?:([^\:]*)\:\/\/)?(?:([^\:\@]*)(?:\:([^\@]*))?\@)?(?:([^\/\:]*))?(?:\:([0-9]*))?\/(\/[^\?#]*(?=.*?\/)\/)?([^\?#]*)?(?:\?([^#]*))?(?:#(.*))?/ - person lepe; 21.12.2016

Я пытался решить эту проблему с помощью javascript, с чем следует справиться:

var url = new URL('http://a:[email protected]:890/path/wah@t/foo.js?foo=bar&bingobang=&[email protected]#foobar/bing/bo@ng?bang');

поскольку (по крайней мере, в Chrome) он анализирует:

{
  "hash": "#foobar/bing/bo@ng?bang",
  "search": "?foo=bar&bingobang=&[email protected]",
  "pathname": "/path/wah@t/foo.js",
  "port": "890",
  "hostname": "example.com",
  "host": "example.com:890",
  "password": "b",
  "username": "a",
  "protocol": "http:",
  "origin": "http://example.com:890",
  "href": "http://a:[email protected]:890/path/wah@t/foo.js?foo=bar&bingobang=&[email protected]#foobar/bing/bo@ng?bang"
}

Однако это не кроссбраузер (https://developer.mozilla.org/en-US/docs/Web/API/URL), поэтому я собрал все вместе, чтобы извлечь те же части, что и выше:

^(?:(?:(([^:\/#\?]+:)?(?:(?:\/\/)(?:(?:(?:([^:@\/#\?]+)(?:\:([^:@\/#\?]*))?)@)?(([^:\/#\?\]\[]+|\[[^\/\]@#?]+\])(?:\:([0-9]+))?))?)?)?((?:\/?(?:[^\/\?#]+\/+)*)(?:[^\?#]*)))?(\?[^#]+)?)(#.*)?

Кредит за это регулярное выражение принадлежит https://gist.github.com/rpflorence, который опубликовал этот jsperf http://jsperf.com/url-parsing (изначально находится здесь: https://gist.github.com/jlong/2428561#comment-310066), который придумал регулярное выражение, это было изначально основан на.

Детали расположены в таком порядке:

var keys = [
    "href",                    // http://user:[email protected]:81/directory/file.ext?query=1#anchor
    "origin",                  // http://user:[email protected]:81
    "protocol",                // http:
    "username",                // user
    "password",                // pass
    "host",                    // host.com:81
    "hostname",                // host.com
    "port",                    // 81
    "pathname",                // /directory/file.ext
    "search",                  // ?query=1
    "hash"                     // #anchor
];

Существует также небольшая библиотека, которая обертывает его и предоставляет параметры запроса:

https://github.com/sadams/lite-url (также доступно в беседке)

Если у вас есть улучшения, создайте запрос на перенос с большим количеством тестов, я приму его и с благодарностью объединю.

person Sam Adams    schedule 02.07.2014
comment
Это замечательно, но действительно может работать с такой версией, которая извлекает поддомены вместо дублированного хоста, имени хоста. Так что если бы у меня было http://test1.dev.mydomain.com/, например, он бы вытащил test1.dev.. - person user692942; 01.09.2014
comment
Это очень хорошо работает. Я искал способ извлечь необычные параметры аутентификации из URL-адресов, и это прекрасно работает. - person Aaron M; 14.04.2017

субдомен и домен сложны, потому что субдомен может состоять из нескольких частей, как и домен верхнего уровня, http://sub1.sub2.domain.co.uk/

 the path without the file : http://[^/]+/((?:[^/]+/)*(?:[^/]+$)?)  
 the file : http://[^/]+/(?:[^/]+/)*((?:[^/.]+\.)+[^/.]+)$  
 the path with the file : http://[^/]+/(.*)  
 the URL without the path : (http://[^/]+/)  

(Markdown не очень дружелюбен к регулярным выражениям)

person tgmdbm    schedule 26.08.2008
comment
Очень полезно - я добавил еще (http(s?)://[^/]+/), чтобы также получать https - person Mojowen; 08.08.2013

Попробуйте следующее:

^((ht|f)tp(s?)\:\/\/|~/|/)?([\w]+:\w+@)?([a-zA-Z]{1}([\w\-]+\.)+([\w]{2,5}))(:[\d]{1,5})?((/?\w+/)+|/?)(\w+\.[\w]{3,4})?((\?\w+=\w+)?(&\w+=\w+)*)?

Он поддерживает HTTP / FTP, поддомены, папки, файлы и т. Д.

Я нашел это при быстром поиске в гугле:

http://geekswithblogs.net/casualjim/archive/2005/12/01/61722.aspx

person Mark Ingram    schedule 26.08.2008

Предложите гораздо более читаемое решение (на Python, но применимо к любому регулярному выражению):

def url_path_to_dict(path):
    pattern = (r'^'
               r'((?P<schema>.+?)://)?'
               r'((?P<user>.+?)(:(?P<password>.*?))?@)?'
               r'(?P<host>.*?)'
               r'(:(?P<port>\d+?))?'
               r'(?P<path>/.*?)?'
               r'(?P<query>[?].*?)?'
               r'$'
               )
    regex = re.compile(pattern)
    m = regex.match(path)
    d = m.groupdict() if m is not None else None

    return d

def main():
    print url_path_to_dict('http://example.example.com/example/example/example.html')

Печать:

{
'host': 'example.example.com', 
'user': None, 
'path': '/example/example/example.html', 
'query': None, 
'password': None, 
'port': None, 
'schema': 'http'
}
person okigan    schedule 26.07.2013

Эта улучшенная версия должна работать так же надежно, как парсер.

   // Applies to URI, not just URL or URN:
   //    http://en.wikipedia.org/wiki/Uniform_Resource_Identifier#Relationship_to_URL_and_URN
   //
   // http://labs.apache.org/webarch/uri/rfc/rfc3986.html#regexp
   //
   // (?:([^:/?#]+):)?(?://([^/?#]*))?([^?#]*)(?:\?([^#]*))?(?:#(.*))?
   //
   // http://en.wikipedia.org/wiki/URI_scheme#Generic_syntax
   //
   // $@ matches the entire uri
   // $1 matches scheme (ftp, http, mailto, mshelp, ymsgr, etc)
   // $2 matches authority (host, user:pwd@host, etc)
   // $3 matches path
   // $4 matches query (http GET REST api, etc)
   // $5 matches fragment (html anchor, etc)
   //
   // Match specific schemes, non-optional authority, disallow white-space so can delimit in text, and allow 'www.' w/o scheme
   // Note the schemes must match ^[^\s|:/?#]+(?:\|[^\s|:/?#]+)*$
   //
   // (?:()(www\.[^\s/?#]+\.[^\s/?#]+)|(schemes)://([^\s/?#]*))([^\s?#]*)(?:\?([^\s#]*))?(#(\S*))?
   //
   // Validate the authority with an orthogonal RegExp, so the RegExp above won’t fail to match any valid urls.
   function uriRegExp( flags, schemes/* = null*/, noSubMatches/* = false*/ )
   {
      if( !schemes )
         schemes = '[^\\s:\/?#]+'
      else if( !RegExp( /^[^\s|:\/?#]+(?:\|[^\s|:\/?#]+)*$/ ).test( schemes ) )
         throw TypeError( 'expected URI schemes' )
      return noSubMatches ? new RegExp( '(?:www\\.[^\\s/?#]+\\.[^\\s/?#]+|' + schemes + '://[^\\s/?#]*)[^\\s?#]*(?:\\?[^\\s#]*)?(?:#\\S*)?', flags ) :
         new RegExp( '(?:()(www\\.[^\\s/?#]+\\.[^\\s/?#]+)|(' + schemes + ')://([^\\s/?#]*))([^\\s?#]*)(?:\\?([^\\s#]*))?(?:#(\\S*))?', flags )
   }

   // http://en.wikipedia.org/wiki/URI_scheme#Official_IANA-registered_schemes
   function uriSchemesRegExp()
   {
      return 'about|callto|ftp|gtalk|http|https|irc|ircs|javascript|mailto|mshelp|sftp|ssh|steam|tel|view-source|ymsgr'
   }
person Shelby Moore    schedule 16.09.2010

/^((?P<scheme>https?|ftp):\/)?\/?((?P<username>.*?)(:(?P<password>.*?)|)@)?(?P<hostname>[^:\/\s]+)(?P<port>:([^\/]*))?(?P<path>(\/\w+)*\/)(?P<filename>[-\w.]+[^#?\s]*)?(?P<query>\?([^#]*))?(?P<fragment>#(.*))?$/

Из моего ответа на аналогичный вопрос. Работает лучше, чем некоторые из других упомянутых, потому что в них были некоторые ошибки (например, не поддерживались имя пользователя / пароль, не поддерживались односимвольные имена файлов, идентификаторы фрагментов были сломаны).

person strager    schedule 14.01.2009

Вы можете получить все http / https, хост, порт, путь, а также запрос, используя объект Uri в .NET. просто сложная задача - разбить хост на субдомен, доменное имя и TLD.

Для этого нет стандарта, и нельзя просто использовать синтаксический анализ строк или регулярное выражение для получения правильного результата. Сначала я использую функцию RegEx, но не все URL-адреса могут правильно анализировать поддомен. Практический способ - использовать список TLD. После определения TLD для URL-адреса левая часть является доменом, а оставшаяся часть - поддоменом.

Однако список необходимо поддерживать, поскольку новые TLD возможны. На данный момент я знаю, что publicsuffix.org поддерживает последний список, и вы можете использовать инструменты парсера имени домена из кода Google, чтобы проанализировать список общедоступных суффиксов и легко получить поддомен, домен и TLD с помощью объекта DomainName: domainName.SubDomain, domainName .Domain и domainName.TLD.

Этот ответ также полезен: Получить субдомен по URL-адресу

КАЛЛМЕЛАНН

person CallMeLaNN    schedule 09.10.2009

Вот тот, который завершен и не зависит от какого-либо протокола.

function getServerURL(url) {
        var m = url.match("(^(?:(?:.*?)?//)?[^/?#;]*)");
        console.log(m[1]) // Remove this
        return m[1];
    }

getServerURL("http://dev.test.se")
getServerURL("http://dev.test.se/")
getServerURL("//ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js")
getServerURL("//")
getServerURL("www.dev.test.se/sdas/dsads")
getServerURL("www.dev.test.se/")
getServerURL("www.dev.test.se?abc=32")
getServerURL("www.dev.test.se#abc")
getServerURL("//dev.test.se?sads")
getServerURL("http://www.dev.test.se#321")
getServerURL("http://localhost:8080/sads")
getServerURL("https://localhost:8080?sdsa")

Распечатки

http://dev.test.se

http://dev.test.se

//ajax.googleapis.com

//

www.dev.test.se

www.dev.test.se

www.dev.test.se

www.dev.test.se

//dev.test.se

http://www.dev.test.se

http://localhost:8080

https://localhost:8080
person mmm    schedule 27.12.2012

Ничего из вышеперечисленного у меня не сработало. Вот что я в итоге использовал:

/^(?:((?:https?|s?ftp):)\/\/)([^:\/\s]+)(?::(\d*))?(?:\/([^\s?#]+)?([?][^?#]*)?(#.*)?)?/
person Skone    schedule 17.01.2013

Мне нравится регулярное выражение, опубликованное в «Javascript: The Good Parts». Он не слишком короткий и не слишком сложный. На этой странице в github также есть код JavaScript, который его использует. Но он может быть адаптирован для любого языка. https://gist.github.com/voodooGQ/4057330

person Yetti99    schedule 31.05.2015

const URI_RE = /^(([^:\/\s]+):\/?\/?([^\/\s@]*@)?([^\/@:]*)?:?(\d+)?)?(\/[^?]*)?(\?([^#]*))?(#[\s\S]*)?$/;
/**
* GROUP 1 ([scheme][authority][host][port])
* GROUP 2 (scheme)
* GROUP 3 (authority)
* GROUP 4 (host)
* GROUP 5 (port)
* GROUP 6 (path)
* GROUP 7 (?query)
* GROUP 8 (query)
* GROUP 9 (fragment)
*/
URI_RE.exec("https://john:[email protected]:123/forum/questions/?tag=networking&order=newest#top");
URI_RE.exec("/forum/questions/?tag=networking&order=newest#top");
URI_RE.exec("ldap://[2001:db8::7]/c=GB?objectClass?one");
URI_RE.exec("mailto:[email protected]");

Выше вы можете найти реализацию javascript с измененным регулярным выражением

person igorzg    schedule 18.04.2021

Java предлагает класс URL, который сделает это. Объекты URL запроса.

Кстати, PHP предлагает parse_url ().

person Chris Bartow    schedule 26.08.2008
comment
Похоже, это не разбирает субдомен? - person Chris Dutrow; 05.03.2010
comment
Аскер попросил регулярное выражение. Класс URL-адреса откроет соединение, когда вы его создадите. - person MikeNereson; 24.11.2011
comment
Класс URL-адреса откроет соединение, когда вы его создадите - это неверно, только когда вы вызываете такие методы, как connect (). Но это правда, что java.net.URL несколько тяжелый. В этом случае лучше использовать java.net.URI. - person jcsahnwaldt Reinstate Monica; 12.05.2012

Я бы рекомендовал не использовать регулярное выражение. Вызов API, такой как WinHttpCrackUrl (), менее подвержен ошибкам.

http://msdn.microsoft.com/en-us/library/aa384092%28VS.85%29.aspx

person Jason    schedule 30.11.2009
comment
А также очень специфичен для платформы. - person Andir; 13.07.2010
comment
Думаю, дело было в том, чтобы использовать библиотеку, а не изобретать велосипед. В Ruby, Python, Perl есть инструменты для разделения URL-адресов, так что хватайте их вместо того, чтобы реализовывать плохой шаблон. - person the Tin Man; 17.01.2011

Я попробовал несколько из них, которые не соответствовали моим потребностям, особенно получившие наибольшее количество голосов, которые не поймали URL без пути (http://example.com/)

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

так что это моя версия, слегка измененная с исходной версией, получившей наибольшее количество голосов:

^((?P<protocol>http[s]?|ftp):\/)?\/?(?P<host>[^:\/\s]+)(?P<path>((\/\w+)*\/)([\w\-\.]+[^#?\s]+))*(.*)?(#[\w\-]+)?$
person Gil Zellner    schedule 23.11.2016

Я строю эту. Очень разрешено не проверять URL-адрес, просто разделяя его.

^((http[s]?):\/\/)?([a-zA-Z0-9-.]*)?([\/]?[^?#\n]*)?([?]?[^?#\n]*)?([#]?[^?#\n]*)$

  • соответствие 1: полный протокол с: // (http или https)
  • совпадение 2: протокол без: //
  • матч 3: хост
  • матч 4: слизняк
  • матч 5: параметр
  • матч 6: якорь

работа

http://
https://
www.demo.com
/slug
?foo=bar
#anchor

https://demo.com
https://demo.com/
https://demo.com/slug
https://demo.com/slug/foo
https://demo.com/?foo=bar
https://demo.com/?foo=bar#anchor
https://demo.com/?foo=bar&bar=foo#anchor
https://www.greate-demo.com/

сбой

#anchor#
?toto?
person CallMarl    schedule 21.10.2020

Использование регулярного выражения http://www.fileformat.info/tool/regex.htm hometoast работает отлично.

Но вот в чем дело: я хочу использовать разные шаблоны регулярных выражений в разных ситуациях в моей программе.

Например, у меня есть этот URL-адрес, и у меня есть перечисление, в котором перечислены все поддерживаемые URL-адреса в моей программе. Каждый объект в перечислении имеет метод getRegexPattern, который возвращает шаблон регулярного выражения, который затем будет использоваться для сравнения с URL-адресом. Если конкретный шаблон регулярного выражения возвращает истину, то я знаю, что этот URL-адрес поддерживается моей программой. Итак, каждое перечисление имеет собственное регулярное выражение в зависимости от того, где оно должно искать внутри URL-адреса.

Предложение Hometoast отличное, но в моем случае я думаю, что это не поможет (если я не скопирую одно и то же регулярное выражение во все перечисления).

Вот почему я хотел, чтобы ответ давал регулярное выражение для каждой ситуации отдельно. Хотя +1 за домашний тост. ;)

person pek    schedule 26.08.2008

Я знаю, что вы утверждаете, что это не зависит от языка, но можете ли вы сказать нам, что вы используете, чтобы мы знали, какие у вас есть возможности регулярных выражений?

Если у вас есть возможности для не захватывающих совпадений, вы можете изменить выражение hometoast, чтобы подвыражения, которые вам не нужны, были настроены следующим образом:

(?:SOMESTUFF)

Вам все равно придется копировать и вставлять (и немного изменять) регулярное выражение в нескольких местах, но это имеет смысл - вы не просто проверяете, существует ли подвыражение, но, скорее, существует ли оно как часть URL. Использование модификатора без захвата для подвыражений может дать вам то, что вам нужно, и ничего больше, что, если я правильно вас понимаю, это то, что вы хотите.

В качестве небольшого примечания, выражение hometoast не должно заключать скобки вокруг 's' для 'https', поскольку в нем только один символ. Квантификаторы количественно определяют один символ (или класс символов, или подвыражение), непосредственно предшествующий им. Так:

https?

будет просто соответствовать 'http' или 'https'.

person Brian Warshaw    schedule 26.08.2008

regexp, чтобы получить URL-путь без файла.

url = 'http://domain/dir1/dir2/somefile' url.scan (/ ^ ( http: // [^ /] +) ((?: / [^ /] +) + (? = /))? /? (?: [^ /] +)? $ / i) .to_s

Это может быть полезно для добавления относительного пути к этому URL-адресу.

person Community    schedule 16.07.2009

Регулярное выражение для полного синтаксического анализа довольно ужасно. Я включил именованные обратные ссылки для удобочитаемости и разбил каждую часть на отдельные строки, но это все равно выглядит так:

^(?:(?P<protocol>\w+(?=:\/\/))(?::\/\/))?
(?:(?P<host>(?:(?:&(?:amp|apos|gt|lt|nbsp|quot|bull|hellip|[lr][ds]quo|[mn]dash|permil|\#[1-9][0-9]{1,3}|[A-Za-z][0-9A-Za-z]+);)|[^\/?#:]+)(?::(?P<port>[0-9]+))?)\/)?
(?:(?P<path>(?:(?:&(?:amp|apos|gt|lt|nbsp|quot|bull|hellip|[lr][ds]quo|[mn]dash|permil|\#[1-9][0-9]{1,3}|[A-Za-z][0-9A-Za-z]+);)|[^?#])+)\/)?
(?P<file>(?:(?:&(?:amp|apos|gt|lt|nbsp|quot|bull|hellip|[lr][ds]quo|[mn]dash|permil|\#[1-9][0-9]{1,3}|[A-Za-z][0-9A-Za-z]+);)|[^?#])+)
(?:\?(?P<querystring>(?:(?:&(?:amp|apos|gt|lt|nbsp|quot|bull|hellip|[lr][ds]quo|[mn]dash|permil|\#[1-9][0-9]{1,3}|[A-Za-z][0-9A-Za-z]+);)|[^#])+))?
(?:#(?P<fragment>.*))?$

То, что требует, чтобы он был настолько подробным, заключается в том, что, за исключением протокола или порта, любая из частей может содержать объекты HTML, что делает определение фрагмента довольно сложным. Итак, в последних нескольких случаях - хост, путь, файл, строка запроса и фрагмент - мы разрешаем любой объект html или любой символ, кроме ? или #. Регулярное выражение для html-сущности выглядит так:

$htmlentity = "&(?:amp|apos|gt|lt|nbsp|quot|bull|hellip|[lr][ds]quo|[mn]dash|permil|\#[1-9][0-9]{1,3}|[A-Za-z][0-9A-Za-z]+);"

Когда это извлекается (я использовал синтаксис усов для его представления), он становится немного более разборчивым:

^(?:(?P<protocol>(?:ht|f)tps?|\w+(?=:\/\/))(?::\/\/))?
(?:(?P<host>(?:{{htmlentity}}|[^\/?#:])+(?::(?P<port>[0-9]+))?)\/)?
(?:(?P<path>(?:{{htmlentity}}|[^?#])+)\/)?
(?P<file>(?:{{htmlentity}}|[^?#])+)
(?:\?(?P<querystring>(?:{{htmlentity}};|[^#])+))?
(?:#(?P<fragment>.*))?$

В JavaScript, конечно, нельзя использовать именованные обратные ссылки, поэтому регулярное выражение становится

^(?:(\w+(?=:\/\/))(?::\/\/))?(?:((?:(?:&(?:amp|apos|gt|lt|nbsp|quot|bull|hellip|[lr][ds]quo|[mn]dash|permil|\#[1-9][0-9]{1,3}|[A-Za-z][0-9A-Za-z]+);)|[^\/?#:]+)(?::([0-9]+))?)\/)?(?:((?:(?:&(?:amp|apos|gt|lt|nbsp|quot|bull|hellip|[lr][ds]quo|[mn]dash|permil|\#[1-9][0-9]{1,3}|[A-Za-z][0-9A-Za-z]+);)|[^?#])+)\/)?((?:(?:&(?:amp|apos|gt|lt|nbsp|quot|bull|hellip|[lr][ds]quo|[mn]dash|permil|\#[1-9][0-9]{1,3}|[A-Za-z][0-9A-Za-z]+);)|[^?#])+)(?:\?((?:(?:&(?:amp|apos|gt|lt|nbsp|quot|bull|hellip|[lr][ds]quo|[mn]dash|permil|\#[1-9][0-9]{1,3}|[A-Za-z][0-9A-Za-z]+);)|[^#])+))?(?:#(.*))?$

и в каждом совпадении протокол - \1, хост - \2, порт - \3, путь \4, файл \5, строка запроса \6 и фрагмент \7.

person Steve K    schedule 02.09.2016

Я пробовал это регулярное выражение для разбора разделов URL:

^((http[s]?|ftp):\/)?\/?([^:\/\s]+)(:([^\/]*))?((\/?(?:[^\/\?#]+\/+)*)([^\?#]*))(\?([^#]*))?(#(.*))?$

URL: https://www.google.com/my/path/sample/asd-dsa/this?key1=value1&key2=value2

Матчи:

Group 1.    0-7 https:/
Group 2.    0-5 https
Group 3.    8-22    www.google.com
Group 6.    22-50   /my/path/sample/asd-dsa/this
Group 7.    22-46   /my/path/sample/asd-dsa/
Group 8.    46-50   this
Group 9.    50-74   ?key1=value1&key2=value2
Group 10.   51-74   key1=value1&key2=value2
person Bilal Demir    schedule 22.07.2020

Лучший ответ, предложенный здесь, не сработал для меня, потому что мои URL-адреса также содержат порт. Однако изменение его на следующее регулярное выражение сработало для меня:

^((http[s]?|ftp):\/)?\/?([^:\/\s]+)(:\d+)?((\/\w+)*\/)([\w\-\.]+[^#?\s]+)(.*)?(#[\w\-]+)?$
person Hritik Soni    schedule 30.11.2020

Мне нужен был REGEX для анализа компонентов URL-адреса в Java. Вот что я использую:

"^(?:(http[s]?|ftp):/)?/?" +    // METHOD
"([^:^/^?^#\\s]+)" +            // HOSTNAME
"(?::(\\d+))?" +                // PORT
"([^?^#.*]+)?" +                // PATH
"(\\?[^#.]*)?" +                // QUERY
"(#[\\w\\-]+)?$"                // ID

Фрагмент кода Java:

final Pattern pattern = Pattern.compile(
        "^(?:(http[s]?|ftp):/)?/?" +    // METHOD
        "([^:^/^?^#\\s]+)" +            // HOSTNAME
        "(?::(\\d+))?" +                // PORT
        "([^?^#.*]+)?" +                // PATH
        "(\\?[^#.]*)?" +                // QUERY
        "(#[\\w\\-]+)?$"                // ID
);
final Matcher matcher = pattern.matcher(url);

System.out.println("     URL: " + url);

if (matcher.matches())
{
    System.out.println("  Method: " + matcher.group(1));
    System.out.println("Hostname: " + matcher.group(2));
    System.out.println("    Port: " + matcher.group(3));
    System.out.println("    Path: " + matcher.group(4));
    System.out.println("   Query: " + matcher.group(5));
    System.out.println("      ID: " + matcher.group(6));
    
    return matcher.group(2);
}

System.out.println();
System.out.println();
person MattWeiler    schedule 01.06.2021

String s = "https://www.thomas-bayer.com/axis2/services/BLZService?wsdl";

String regex = "(^http.?://)(.*?)([/\\?]{1,})(.*)";

System.out.println("1: " + s.replaceAll(regex, "$1"));
System.out.println("2: " + s.replaceAll(regex, "$2"));
System.out.println("3: " + s.replaceAll(regex, "$3"));
System.out.println("4: " + s.replaceAll(regex, "$4"));

Обеспечит следующий вывод:
1: https: //
2: www.thomas-bayer.com
3: /
4: axis2 / services / BLZService? Wsdl

Если вы измените URL-адрес на
String s = "https://www.thomas-bayer.com?wsdl=qwerwer&ttt=888 "; вывод будет следующим:
1: https: //
2: www.thomas-bayer.com
3:?
4: wsdl = qwerwer & ttt = 888

наслаждайтесь ..
Йоси Лев

person ylev    schedule 24.12.2015
comment
Не обрабатывает порты. Не зависит от языка. - person Ohgodwhy; 21.05.2020