Связать текст с регулярными выражениями в Java - PullRequest
7 голосов
/ 10 марта 2009

У меня есть текстовая область wysiwyg в веб-приложении Java. Пользователи могут вводить текст и стилизовать его или вставлять текст в формате HTML.

Я пытаюсь связать текст. Это означает преобразование всех возможных URL-адресов в тексте в их «рабочий аналог», то есть добавление ... .

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

String r = "http(s)?://([\\w+?\\.\\w+])+([a-zA-Z0-9\\~\\!\\@\\#\\$\\%\\^\\&\\*\\(\\)_\\-\\=\\+\\\\\\/\\?\\.\\:\\;\\'\\,]*)?";
Pattern pattern = Pattern.compile(r, Pattern.DOTALL | Pattern.UNIX_LINES | Pattern.CASE_INSENSITIVE);
Matcher matcher = pattern.matcher(comment);
comment = matcher.replaceAll("<a href=\"$0\">$0</a>"); // group 0 is the whole expression

Но проблема в том, что есть какой-то уже отформатированный текст, то есть он уже имеет теги ... .

Поэтому я ищу способ, которым шаблон не будет совпадать с всякий раз, когда он находит текст между двумя тегами HTML () . Я читал, что этого можно добиться с помощью lookahead или lookbehind , но я все еще не могу заставить его работать. Я уверен, что я делаю это неправильно, потому что регулярное выражение по-прежнему совпадает. И да, я играю / отлаживаю группы, меняю от 0 до 1 и т. Д.

Есть идеи?

Ответы [ 5 ]

9 голосов
/ 10 марта 2009

Вы рядом. Вы можете использовать «негативный взгляд назад», например, так:

(?<!href=")http:// etc

Все результаты, которым предшествует href, будут игнорироваться.

1 голос
/ 10 марта 2009

Если вы действительно хотите сделать это с помощью регулярных выражений, тогда:

   String r = "(?<![=\"\\/>])http(s)?://([\\w+?\\.\\w+])+([a-zA-Z0-9\\~\\!\\@\\#\\$\\%\\^\\&amp;\\*\\(\\)_\\-\\=\\+\\\\\\/\\?\\.\\:\\;\\'\\,]*)?";

например. убедитесь, что URL не соответствует a = "или />

1 голос
/ 10 марта 2009

Если вы хотите использовать регулярные выражения (хотя я думаю, что сначала разбирается в XML / HTML более надежно), я думаю, что заблаговременное или -полезное имеет смысл. Первый удар может добавить это в конце вашего регулярного выражения:

(?!</a>)

Значение: не совпадать, если после этого есть закрывающий тег. (Конечно, это может быть изменено навсегда.) Однако это не очень хорошо работает, потому что, учитывая строку

<a href="...">http://example.com/</a>

Это регулярное выражение будет пытаться сопоставить «http://example.com/", с ошибкой из-за заблаговременного ожидания (как мы надеемся), а затем возврат назад жадного квалификатора, который будет в конце и совпадать» http://example.com" вместо этого, который не имеет после него.

Вы можете решить последнюю проблему, используя притяжательный квалификатор на своих +, * и? операторы - просто вставьте + после них. Это предотвращает их обратное отслеживание. Это, вероятно, также хорошо по причинам производительности.

Это работает для меня (обратите внимание на три дополнительных +):

String r = "http(s)?://([\\w+?\\.\\w+])++([a-zA-Z0-9\\~\\!\\@\\#\\$\\%\\^\\&amp;\\*\\(\\)_\\-\\=\\+\\\\\\/\\?\\.\\:\\;\\'\\,]*+)?+(?!</a>)";
0 голосов
/ 10 марта 2009

Если вам нужно накатить свои собственные, хотя бы посмотрите на алгоритмы / шаблоны, используемые в реализации Markdown с открытым исходным кодом, например, MarkdownJ .

0 голосов
/ 10 марта 2009

Возможно, HTML-разбор будет более подходящим для вас (например, htmlparser ). Тогда у вас могут быть html-узлы и только «ссылки» в тексте, а не в атрибутах.

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