Пример поиска и подсветки ссылок и e-mail в тексте
Введем вспомогательный подшаблон, который будет повторяться в других подшаблонах:
my $wb='(?![A-Za-z0-9])';
Он означает, что справа не должно быть ни буквы, ни цифры.
Для зоны (это может быть com, net, org, ru, de, name, museum, co.uk… ) имеется такой подшаблон:
my $zone=<<ZONE; (?i:(?(?=[a-z]{3}$wb)(?>com|net|org|edu|biz|gov|int|mil)| (?(?=[a-z]{2}$wb)[a-z]{2}| (?(?=[a-z]{4}$wb)(?>info|aero|name)| (?(?=[a-z]{6}$wb)museum|(?!) ) ) ) ) (?>\\.[a-z]{2}$wb)?) ZONE
После имени хоста через двоеточие может идти порт:
my $port="(?::\\d{1,5}$wb)";
А после зоны может идти хвост, который содержит множество всяких параметров, передаваемых с URL:
my $tail=<<TAIL; (?:[/?] (?>[^.,"'<>()[\\]{}\\s\\x7F-\\xFF]*) (?:(?>[.,?]+) (?:[^"'<>()[\\]{}\\s\\x7F-\\xFF]+) )* (?<![,.?!-]) ) TAIL
В конце стоит заглядывание назад
(?<![,.?!-])
которое учитывает, что после URL могут стоять знаки препинания, которые в него не входят.
Все регулярное выражение для поиска URL в тексте выглядит немного страшновато:
my $re=<<RE; ( (?>($protocol)(?(2)(?>$host$zone)|$host$zone) (?![A-Za-z0-9])| (?<![A-Za-z0-9_\\\@-]) (?<!\\.(?!(?i:www))) $subdom$zone(?![A-Za-z0-9_.-]*\\\@) ) (?>(?>$port?(?>\\\@$host$zone(?![A-Za-z0-9_.-]*\\\@))?)?) ) ($tail?) RE
Это выражение учитывает заход через прокси-сервер вида
http://proxy.com@site.com/
Часть URL от начала до хвоста, который может идти после символов / или ?, мы берем в нумерованную переменную $1. Эту часть URL внутри тега <a мы будем выводить маленькими буквами, а для отображения на странице будем выводить в том виде, в котором ее ввел автор сообщения. Протокол мы возьмем в переменную $2. Если протокола нет, то при форматировании ссылки мы подставим на его место текст http://. Хвост $tail мы захватываем в переменную $3.
Внутри переменной $re встречается эскейп-последовательности \@. Но т.к. внутри текста here doc \ и @ являются метасимволами, то, чтобы в результате получить последовательность \@, надо написать \\\@. Тогда при обработке такого текста \\ превратится в \, а \@ превратится в @, и в конце получится нужная последовательность \@. Для проверки напечатайте переменную $re.
Программа должна "подсвечивать" ссылки в тексте. Например, имеем текст
Look at:aaa.Museum.
Это должно превратиться в
Look at:<a href="aaa.museum" target="_blank">aaa.Museum</a>.
Здесь возможный URL отделяется от прилипших справа и слева символов и оформляется в тег <a. Внутри строки href имя хоста и зона записываются строчными буквами, а в тексте, который будет виден на странице, форматирования не производится. Еще программа должна учесть, что в хвосте URL (имена подкаталогов и параметры) форматировать текст нельзя, т. к. эти слова чувствительны к регистру символов.
Возьмем в качестве тестового такой текст:
my $text=<<TEXT; URLs: Ftp://a.com/AAa Look at:aaa.Museum. http://www.proxy.com:80\@www.site.com/ http://proxy.com:80\@site.com/ http://proxy.com\@site.com/ aAaa.com.au.rr.ggg Zwww.Yahoo.co.uk Фforum.abcd.de www.Abc.eu П123.123.123.1234.com/?q=aaa http://Abc.Tk Ahttp://www.Abc.pt/AAa http://abc.au/query/vid.cam.dig/sony.dcrhc15.htm#full_image Ф.Www.old-avto.tk NOT URLs: aaa.museumm http://aaa.museumm, http://-aaa.com www._aaa.com www.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.com TEXT