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

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

123 голосов
/ 26 августа 2008

Учитывая 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

Ответы [ 24 ]

132 голосов
/ 26 августа 2008

Одно регулярное выражение для анализа и разбиения полный 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

Вы можете затем легко разобрать хост (с разделителями '.').

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

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

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

76 голосов
/ 18 сентября 2012

Я понимаю, что опаздываю на вечеринку, но есть простой способ позволить браузеру проанализировать для вас 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
*/
52 голосов
/ 05 ноября 2014

Я опоздал на вечеринку на несколько лет, но я удивлен, что никто не упомянул, что в спецификации 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:

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

31 голосов
/ 21 ноября 2008

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

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

Следующее является модифицированной версией:

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

Положение деталей выглядит следующим образом:

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

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

function getFileName(path) {
    return path.match(/^((http[s]?|ftp):\/)?\/?([^:\/\s]+)(:([^\/]*))?((\/[\w\/-]+)*\/)([\w\-\.]+[^#?\s]+)(\?([^#]*))?(#(.*))?$/i)[8];
}
11 голосов
/ 15 августа 2012

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

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

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

ftp://user:pass@www.cs.server.com: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://admin@www.cs.server.com

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

["mailto", "admin", undefined, "www.cs", "server", "com", undefined, undefined, undefined, undefined, undefined] 
7 голосов
/ 02 июля 2014

Я пытался решить эту проблему в javascript, который должен быть обработан:

var url = new URL('http://a:b@example.com:890/path/wah@t/foo.js?foo=bar&bingobang=&king=kong@kong.com#foobar/bing/bo@ng?bang');

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

{
  "hash": "#foobar/bing/bo@ng?bang",
  "search": "?foo=bar&bingobang=&king=kong@kong.com",
  "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:b@example.com:890/path/wah@t/foo.js?foo=bar&bingobang=&king=kong@kong.com#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:pass@host.com:81/directory/file.ext?query=1#anchor
    "origin",                  // http://user:pass@host.com: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 (также доступно на беседке)

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

6 голосов
/ 27 июля 2013

Предложите гораздо более удобочитаемое решение (в 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'
}
5 голосов
/ 26 августа 2008

субдомен и домен сложны, потому что субдомен может состоять из нескольких частей, как и домен верхнего уровня, 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://[^/]+/)  

(Уценка не очень дружит с регулярными выражениями)

5 голосов
/ 26 августа 2008

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

^((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, субдомены, папки, файлы и т. Д.

Я нашел это из быстрого поиска Google:

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

5 голосов
/ 16 сентября 2010

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

   // 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'
   }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...