Получение части URL-адреса (регулярное выражение)
учитывая URL (одна строка):
http://test.example.com/dir/subdir/file.html
Как я могу извлечь следующие части с помощью регулярного выражения:
- поддомене (тест)
- домен (example.com)
- путь без файла (/dir/subdir/)
- файл (file.html)
- путь к файлу (/dir/subdir / file.html)
- URL без пути (http://test.example.com)
- (добавьте любой другой, который вы считаете полезным)
регулярное выражение должно работать правильно, даже если я ввожу следующий URL:
http://example.example.com/example/example/example.html
спасибо.
24 ответов:
одно регулярное выражение для разбора и распада a полный 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 ['$&'],
протокол:регулярное выражение.$2,
ведущий:регулярное выражение.$3,
путь:регулярное выражение.$4,
file: RegExp.$6,
запрос:регулярное выражение.$7,
хэш:регулярное выражение.8$
затем вы можете дополнительно проанализировать хост ('.'с разделителями) довольно легко.
что я хотел сделать, это использовать что-то вроде этого:
/* ^(.*:)//([A-Za-z0-9\-\.]+)(:[0-9]+)?(.*)$ */ proto host port the-restдальнейший разбор "остальное", чтобы быть как можно более конкретным. Делать это в одном регулярном выражении, ну, немного безумно.
Я понимаю, что опаздываю на вечеринку, но есть простой способ позволить браузеру разобрать 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 */
Я на несколько лет опоздал на вечеринку, но я удивлен, что никто не упомянул, что спецификация единого идентификатора ресурса имеет раздел по разбору URI с регулярным выражением. Регулярное выражение, написанное Бернерсом-Ли и др., есть:
^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))? 12 3 4 5 6 7 8 9цифры во второй строке выше предназначены только для облегчения чтения; они указывают опорные точки для каждого подвыражения (т. е. парная скобка). Мы ссылаемся на значение, которое соответствует для подвыражения как.$ Например, сопоставление приведенного выше выражения с
http://www.ics.uci.edu/pub/ietf/uri/#Relatedприводит к следующим совпадениям подвыражений:
= http: = http = //www.ics.uci.edu = www.ics.uci.edu = /pub/ietf/uri/ = <undefined> = <undefined> = #Related = Relatedдля чего это стоит, я обнаружил, что мне пришлось избегать прямых косых черт в JavaScript:
^(([^:\/?#]+):)?(\/\/([^\/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?
Я нашел самый высокий голос Ответ (Ответ hometoast) не работает идеально для меня. Две проблемы:
- не может обрабатывать номер порта.
- хэш-часть сломана.
ниже приведена измененная версия:
^((http[s]?|ftp):\/)?\/?([^:\/\s]+)(:([^\/]*))?((\/\w+)*\/)([\w\-\.]+[^#?\s]+)(\?([^#]*))?(#(.*))?$положение частей следующим образом:
int SCHEMA = 2, DOMAIN = 3, PORT = 5, PATH = 6, FILE = 8, QUERYSTRING = 9, HASH = 12редактировать опубликовано anon user:
function getFileName(path) { return path.match(/^((http[s]?|ftp):\/)?\/?([^:\/\s]+)(:([^\/]*))?((\/[\w\/-]+)*\/)([\w\-\.]+[^#?\s]+)(\?([^#]*))?(#(.*))?$/i)[8]; }
мне нужно регулярное выражение, чтобы соответствовать все 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]
Я пытался решить эту проблему в 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 (также доступно на bower)
если у вас есть улучшение, пожалуйста создайте запрос на вытягивание с большим количеством тестов, и я приму и сольюсь с благодарностью.
поддомен и домен сложны, потому что поддомен может иметь несколько частей, как и домен верхнего уровня,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 не очень дружелюбен к регулярным выражениям)
эта улучшенная версия должна работать так же надежно, как парсер.
// 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 // matches scheme (ftp, http, mailto, mshelp, ymsgr, etc) // matches authority (host, user:pwd@host, etc) // matches path // matches query (http GET REST api, etc) // 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' }
попробуйте следующее:
^((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
/^((?P<scheme>https?|ftp):\/)?\/?((?P<username>.*?)(:(?P<password>.*?)|)@)?(?P<hostname>[^:\/\s]+)(?P<port>:([^\/]*))?(?P<path>(\/\w+)*\/)(?P<filename>[-\w.]+[^#?\s]*)?(?P<query>\?([^#]*))?(?P<fragment>#(.*))?$/из моего ответа на аналогичный вопрос. Работает лучше, чем некоторые другие упомянутые, потому что у них были некоторые ошибки (например, не поддерживающие имя пользователя/пароль, не поддерживающие односимвольные имена файлов, фрагментные идентификаторы разбиваются).
предложите гораздо более читаемое решение (в 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' }
вы можете получить все http / https, хост, порт, путь, а также запрос с помощью объекта Uri в .NET. просто сложная задача состоит в том, чтобы разбить Хост на поддомен, доменное имя и TLD.
нет стандарта, чтобы сделать это, и не может быть просто использовать синтаксический анализ строк или регулярное выражение для получения правильного результата. Во-первых, я использую функцию RegEx, но не все URL-адреса могут быть правильно проанализированы поддоменом. Практический способ заключается в использовании списка дву. После определения TLD для URL-адреса левая часть домен, а остальные-поддомен.
однако список должен поддерживать его, поскольку новые дву возможны. Текущий момент, который я знаю, это publicsuffix.org поддерживайте последний список, и вы можете использовать инструменты DomainName-parser из кода google для анализа списка общедоступных суффиксов и легко получить поддомен, домен и TLD с помощью объекта DomainName: domainName.Поддомен, доменное имя.Домен и доменное имя.ДВУ.
этот ответ полезным: получить поддомен от a URL
CaLLMeLaNN
вот тот, который является полным, и не полагается на какой-либо протокол.
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
ни один из выше работал для меня. Вот что я в конечном итоге использовал:
/^(?:((?:https?|s?ftp):)\/\/)([^:\/\s]+)(?::(\d*))?(?:\/([^\s?#]+)?([?][^?#]*)?(#.*)?)?/
Мне нравится выражение, которое было опубликовано в "JavaScript: в хорошие части". Его не слишком короткий и не слишком сложный. Эта страница на github также имеет код JavaScript, который его использует. Но он может быть адаптирован для любого языка. https://gist.github.com/voodooGQ/4057330
Java предлагает класс URL, который будет делать это. объекты URL запроса.
на стороне Примечание, PHP предлагает parse_url ().
Я бы рекомендовал не использовать регулярное выражение. Вызов API, как WinHttpCrackUrl () меньше ошибок.
http://msdn.microsoft.com/en-us/library/aa384092%28VS.85%29.aspx
используя http://www.fileformat.info/tool/regex.htm регулярное выражение hometoast отлично работает.
но вот дело, я хочу использовать разные шаблоны регулярных выражений в разных ситуациях в моей программе.
например, у меня есть этот URL, и у меня есть перечисление, которое перечисляет все поддерживаемые URL в моей программе. Каждый объект в перечислении имеет метод getRegexPattern, который возвращает шаблон регулярного выражения,который затем будет использоваться для сравнения с URL. Если конкретный регулярное выражение pattern возвращает true, то я знаю, что этот URL поддерживается моей программой. Таким образом, каждое перечисление имеет свое собственное регулярное выражение в зависимости от того, где оно должно выглядеть внутри URL.
предложение Hometoast отлично, но в моем случае я думаю, что это не поможет (если я не скопирую одно и то же регулярное выражение во всех перечислениях).
вот почему я хотел, чтобы ответ давал регулярное выражение для каждой ситуации отдельно. Хотя +1 для родного края. ;)
Я знаю, что вы утверждаете, что язык-агностик по этому поводу, но можете ли вы сказать нам, что вы используете, чтобы мы знали, какие возможности regex у вас есть?
Если у вас есть возможности для не захвата совпадений, вы можете изменить выражение hometoast так, чтобы подвыражения, которые вы не заинтересованы в захвате, были настроены следующим образом:
(?:SOMESTUFF)вам все равно придется скопировать и вставить (и немного изменить) регулярное выражение в несколько мест, но это делает sense--вы не просто проверяете, существует ли подвыражение, а скорее, если оно существует как часть URL. Использование модификатора без захвата для подвыражений может дать вам то, что вам нужно, и ничего больше, что, если я правильно читаю вас, это то, что вы хотите.
Так же, как маленькая, маленькая заметка, выражение hometoast не нужно ставить скобки вокруг " s " для "https", так как у него там только один символ. Кванторы количественно определяют один символ (или символьный класс или подвыражение) непосредственно перед ними. Итак:
https?будет соответствовать "http" или "https" просто отлично.
регулярное выражение, чтобы получить URL-путь без файла.
url ='http://domain/dir1/dir2/somefile' url. scan (/^(http://[^/]+)((?:/[^/]+)+(?=/))?/?(?:[^/]+)?$/i). to_s
Это может быть полезно для добавления относительного пути к этому url.
String s = "https://www.thomas-bayer.com/axis2/services/BLZService?wsdl"; String regex = "(^http.?://)(.*?)([/\?]{1,})(.*)"; System.out.println("1: " + s.replaceAll(regex, "")); System.out.println("2: " + s.replaceAll(regex, "")); System.out.println("3: " + s.replaceAll(regex, "")); System.out.println("4: " + s.replaceAll(regex, ""));обеспечит следующий вывод:
1: https://
2: www.thomas-bayer.com
3: /
4: axis2 / услуги / BLZService?wsdl
Если вы измените URL на
Строка s = "https://www.thomas-bayer.com?wsdl=qwerwer&ttt=888"; результат будет следующим:
1: https://
2: www.thomas-bayer.com
3: ?
Четыре: wsdl=qwerwer&ttt=888наслаждайтесь..
Йоси Лев
регулярное выражение для полного разбора довольно ужасно. Я включил именованные обратные ссылки для удобочитаемости и разбил каждую часть на отдельные строки, но все равно выглядит так:
^(?:(?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]+);)|[^#])+))?(?:#(.*))?$и в каждом матче, протокол
узелпортпутьфайл, в строке, и фрагмент.
я попробовал несколько из них, которые не покрывали мои потребности, особенно самые высокие проголосовали, которые не поймали url без пути (http://example.com/)
также отсутствие имен групп сделало его непригодным для использования в ansible (или, возможно, мои навыки jinja2 отсутствуют).
Итак, это моя версия немного изменена с источником, являющимся самой высокой версией голосования здесь:
^((?P<protocol>http[s]?|ftp):\/)?\/?(?P<host>[^:\/\s]+)(?P<path>((\/\w+)*\/)([\w\-\.]+[^#?\s]+))*(.*)?(#[\w\-]+)?$
//USING REGEX /** * Parse URL to get information * * @param url the URL string to parse * @return parsed the URL parsed or null */ var UrlParser = function (url) { "use strict"; var regx = /^(((([^:\/#\?]+:)?(?:(\/\/)((?:(([^:@\/#\?]+)(?:\:([^:@\/#\?]+))?)@)?(([^:\/#\?\]\[]+|\[[^\/\]@#?]+\])(?:\:([0-9]+))?))?)?)?((\/?(?:[^\/\?#]+\/+)*)([^\?#]*)))?(\?[^#]+)?)(#.*)?/, matches = regx.exec(url), parser = null; if (null !== matches) { parser = { href : matches[0], withoutHash : matches[1], url : matches[2], origin : matches[3], protocol : matches[4], protocolseparator : matches[5], credhost : matches[6], cred : matches[7], user : matches[8], pass : matches[9], host : matches[10], hostname : matches[11], port : matches[12], pathname : matches[13], segment1 : matches[14], segment2 : matches[15], search : matches[16], hash : matches[17] }; } return parser; }; var parsedURL=UrlParser(url); console.log(parsedURL);
Comments