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

Получение частей 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 ]

4 голосов
/ 14 января 2009
/^((?P<scheme>https?|ftp):\/)?\/?((?P<username>.*?)(:(?P<password>.*?)|)@)?(?P<hostname>[^:\/\s]+)(?P<port>:([^\/]*))?(?P<path>(\/\w+)*\/)(?P<filename>[-\w.]+[^#?\s]*)?(?P<query>\?([^#]*))?(?P<fragment>#(.*))?$/

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

2 голосов
/ 17 января 2013

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

/^(?:((?:https?|s?ftp):)\/\/)([^:\/\s]+)(?::(\d*))?(?:\/([^\s?#]+)?([?][^?#]*)?(#.*)?)?/
2 голосов
/ 09 октября 2009

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

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

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

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

CaLLMeLaNN

2 голосов
/ 01 июня 2015

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

2 голосов
/ 27 декабря 2012

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

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
1 голос
/ 30 ноября 2009

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

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

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

Java предлагает класс URL, который будет делать это. Запрос объектов URL.

Кроме того, PHP предлагает parse_url () .

1 голос
/ 23 ноября 2016

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

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

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

^((?P<protocol>http[s]?|ftp):\/)?\/?(?P<host>[^:\/\s]+)(?P<path>((\/\w+)*\/)([\w\-\.]+[^#?\s]+))*(.*)?(#[\w\-]+)?$
0 голосов
/ 16 августа 2017
//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);
0 голосов
/ 02 сентября 2016

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

^(?:(?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.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...