Регулярное выражение для соответствия как относительным, так и абсолютным URL - PullRequest
8 голосов
/ 16 июня 2009

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

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

РЕДАКТИРОВАТЬ: Чтобы уточнить, что я пытаюсь сделать, это выбрать все URI из документа (не HTML-документ).

Ответы [ 6 ]

8 голосов
/ 16 июня 2009
(
  ((http|https|ftp)://([\w-\d]+\.)+[\w-\d]+){0,1}  // Capture domain names or IP addresses
  (/[\w~,;\-\./?%&+#=]*)                // Capture paths, including relative
)

Обоснование этого ответа:

  1. Все это сгруппировано, так что вы можете выбрать весь URL
  2. Часть протокола является необязательной, но если она указана, также следует указать имя хоста или IP-адрес (оба из которых имеют меньше разрешенных символов, чем остальная часть URI).
  3. "/" в начале также необязательно. Пути могут быть в форме «images / 1.gif», которые относятся к текущему пути, а не к имени хоста.

Предостережения:

  1. mailto и file URI не поддерживаются.
  2. URL-адреса, отслеживаемые точкой (например, в конце предложения без кавычек), будут включать конечный период.
  3. Из-за # 3 выше, он собирается захватывать все виды вещей. Если вы можете проверить, что все пути не относительно, вы можете добавить «/» вне скобок и, следовательно, потребовать его.
  4. Если все URI находятся в атрибутах HTML (A, LINK, IMG и т. Д.), Вы можете гораздо точнее нацеливать URI, захватывая только в кавычках или, по крайней мере, только в тегах HTML.

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

2 голосов
/ 16 июня 2009

Это хитро, потому что в URL-адресах так много допустимых символов (до того, как они будут закодированы в URL).

Вот мой снимок:

(http:/|https:/)?(/[^\s"'<>]+)+/?

Также похоже на Алекса. Единственная проблема, которую я обнаружил с Алексом, заключается в том, что она не будет соответствовать таким вещам, как знаки фунта, тире и тому подобное. В то время как мой будет соответствовать всему этому.

РЕДАКТИРОВАТЬ - Фактически, единственное, что мешает ему быть слишком жадным, - это инструкция НЕ сопоставлять пробелы, кавычки, апострофы или шевроны.

2 голосов
/ 16 июня 2009
(http:\/)?(\/[\w\.\-]+)+\/?

Похож на Алекса.

1 голос
/ 16 июня 2009
(http:/)?(/[\w.]+)+/?

соответствует этому, но, может быть, вы имели в виду более строгие условия?

0 голосов
/ 16 июня 2009

Я использовал именование групп захвата. Мы получаем лучшие совпадения, когда схема присутствует. Как www.foo.com/bar будет соответствовать только /bar.

(?:
  (?:(?<scheme>https?|file)://)
  (?<host>[^/]+)
  (?<path>/(?:[^\s])+)?
)
|
(?<path>/(?:[^\s])+)

Это то, что вы могли бы сделать для JavaScript

var result = text.match(/(?:(?:(https?|file):\/\/)([^\/]+)(\/(?:[^\s])+)?)|(\/(?:[^\s])+)/g);

Данные испытаний

sadfasdf /foo/bar/ba090z.gif asdfasdf /foo/bar/ sadfasdf asdflkj; http://www.foo.com/foo/bar some stuff http://user:pw@www.foo.com:80/r?stuff%20stuff

user:pw@www.foo.com:80/r?stuff%20stuff
0 голосов
/ 16 июня 2009

Не легко, и вы, возможно, в конечном итоге поймали "слишком много URI", однако как насчет:

((http://|https://)([^/])+)*(/([^\s])*(/))(((\w)*\.[\w]{3,10})|(\w+))?

По сути, у вас там есть пара групп. Об определении протокола. Один ищет каталог, а другой ищет файл в конце. Но! этот подход очень ограничен. Если вам нужна реальная проверка URI и! Разделение (порт, имя пользователя, пароль, отфильтровывать нежелательные символы!) вы, вероятно, получите более сложное выражение. Удачи!

Обновление:

Вы не просили об этом, однако для тех парней из поисковых систем, которые хотят узнать больше о регулярных выражениях, я бы хотел подключить эту бесплатную программу, которую использовал для этой попытки " The Regex Coach " ( Нет, не связан).

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