Как сопоставить URI в тексте?

Как можно найти URI в блоке текста?

Идея состоит в том, чтобы превратить такие прогоны текстов в ссылки. Это довольно просто сделать, если рассматривать только схемы http (s) и ftp (s); Тем не менее, я предполагаю, что общая проблема (с учетом tel, mailto и других схем URI) намного сложнее (если это вообще возможно).

Я бы предпочел решение в C#, если это возможно. Спасибо.

7 ответов

Регулярные выражения могут оказаться хорошей отправной точкой для этого, хотя общеизвестно, что URI и URL трудно сопоставить с одним шаблоном.

Чтобы проиллюстрировать это, простейшие шаблоны выглядят довольно сложными (в обозначениях Perl 5):

\w+:\/{2}[\d\w-]+(\.[\d\w-]+)*(?:(?:\/[^\s/]*))*

Это будет соответствовать http://example.com/foo/bar-baz

а также ftp://192.168.0.1/foo/file.txt

но вызовет проблемы по крайней мере для них:

  • mailto:support@stackru.com (нет совпадений - нет //, но присутствует @)
  • ftp://192.168.0.1.2 (совпадение, но слишком много цифр, поэтому это недействительный URI)
  • ftp://1000.120.0.1 (совпадение, но для IP-адреса нужны цифры от 0 до 255, поэтому это недопустимый URI)
  • nonexistantscheme://obvious.false.positive
  • http://www.google.com/search?q=uri+regular+expression (Совпадение, но вопрос не в том, я думаю, что это случай с правилом 80:20. Если вы хотите уловить большинство вещей, я бы сделал, как предлагалось, найти подходящее регулярное выражение, если вы не можете написать его самостоятельно.

Если вы смотрите на текст, взятый из достаточно контролируемых источников (например, сгенерированных машиной), то это будет наилучшим вариантом действий.

Если вам абсолютно положительно нужно отлавливать каждый URI, с которым вы сталкиваетесь, и вы смотрите на текст с дикой природы, то я думаю, что я бы искал любое слово с двоеточием в нем, например \s(\w:\S+)\s, Когда у вас есть подходящий кандидат на URI, передайте его реальному парсеру URI в классе URI любой используемой вами библиотеки.

Если вас интересует, почему так сложно написать шаблон URI, я думаю, что определение URI делается с помощью грамматики типа 2, тогда как регулярные выражения могут анализировать языки только из грамматик типа 3.

Является ли что-то URI или нет, зависит от контекста. В общем, единственное, что у них всегда есть общего, это то, что они запускают "имя_схемы:". Название схемы может быть любым (при условии использования юридических символов). Но другие строки также содержат двоеточия, не являющиеся URI.

Поэтому вам нужно решить, какие схемы вас интересуют. Как правило, вы можете обойтись поиском "имя_схемы:", за которым следуют символы до пробела для каждой схемы, которая вас интересует. К сожалению, URI могут содержать пробелы, поэтому, если они встроены в текст, они могут быть неоднозначными. Вы ничего не можете сделать, чтобы решить эту двусмысленность - человек, который написал текст, должен будет это исправить. URI необязательно могут быть заключены в <>. Однако большинство людей этого не делают, поэтому признание этого формата поможет лишь изредка.

В статье Википедии для URI перечислены соответствующие RFC.

[Изменить, чтобы добавить: использование регулярных выражений для полной проверки URI - это кошмар - даже если вы каким-то образом найдете или создадите правильный, он будет очень большим, и его будет сложно комментировать и поддерживать. К счастью, если все, что вы делаете, это подсвечивает ссылки, то вам, вероятно, наплевать на странные ложные срабатывания, поэтому вам не нужно проверять. Просто найдите "http://", "mailto:\S*@" и т. Д.]

Инструмент URL для Ubiquity делает следующее:

findURLs: function(text) {
    var urls = [];
    var matches = text.match(/(\S+\.{1}[^\s\,\.\!]+)/g);
    if (matches) {
        for each (var match in matches) {
            urls.push(match);
        }
    }
    return urls;
},

Для многих протоколов вы можете просто искать "://" без кавычек. Не уверен насчет других, хотя.

Вот фрагмент кода с регулярными выражениями для различных нужд:

http://snipplr.com/view/6889/regular-expressions-for-uri-validationparsing/

Это нелегко сделать, если вы хотите также сопоставить "thing.tld", поскольку обычный текст будет иметь много экземпляров этого шаблона, но если вы хотите сопоставлять только URI, начинающиеся со схемы, вы можете попробовать это регулярное выражение (извините, я не знаю, как подключить его в C#)

(http|https|ftp|mailto|tel):\S+[/a-zA-Z0-9]

Вы можете добавить туда больше схем, и они будут соответствовать схеме до следующего символа пробела, принимая во внимание, что последний символ недопустим (например, как в очень обычной строке " http://www.example.com/".)

Следующее регулярное выражение perl должно выполнить трюк. Есть ли в C# регулярные выражения perl?

/\w+:\/\/[\w][\w\.\/]*/
Другие вопросы по тегам