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

Как можно было бы определить URI в блоке текста?

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

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

Ответ 1

Regexs могут стать хорошей отправной точкой для этого, хотя 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:[email protected] (нет совпадения - нет //, но присутствует @)
  • 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 выполняется с помощью Type-2 gramma, в то время как регулярные выражения могут анализировать только языки из Type-3 grammars.

Ответ 2

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

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

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

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

Ответ 3

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

Ответ 5

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

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

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

Ответ 6

Инструмент 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;
},

Ответ 7

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

/\w+:\/\/[\w][\w\.\/]*/