Как сопоставить URL-адреса как слово, используя регулярное выражение, не используя стандартную границу слова?

Я использую re2/J для извлечения URL-адресов независимо от того, начинаются ли они с регулярного выражения или нет. Я использую довольно простой шаблон,

(?i)((https?://)?(([a-z0-9\\-]+[.])*([a-z0-9\\-]+[.][a-z]+/?)([^\\s()<>]*)))

Однако добавление \b в начале и в конце \b мне мало помогает. он по-прежнему соответствует URL-адресам, которые являются частью электронного письма.

example.com с email@example.com также будет соответствовать. Что-то, чего я пытаюсь избежать. @ считается символом, не являющимся словом, и, следовательно, \b рассматривает его как границу слова.

есть ли хорошее альтернативное решение этой проблемы?

ИЗМЕНИТЬ:

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


person Amogh Talpallikar    schedule 08.12.2016    source источник
comment
В re2, который не поддерживает обходные пути, единственным обходным решением является сопоставление того, что вам не нужно, и захват того, что вам нужно. См. (?i)\S+@\S+.\S+|((?:https?://)?(?:[a-z0-9-]+[.])*[a-z0-9-]+[.][a-z]+/?[^\s()<>]*).   -  person Wiktor Stribiżew    schedule 08.12.2016
comment
@WiktorStribiżew, не могли бы вы подробнее рассказать о захвате. проверьте мое редактирование.   -  person Amogh Talpallikar    schedule 08.12.2016
comment
Я не знаю, позволяет ли re2 использовать метод обратного вызова внутри метода замены регулярного выражения. Обычное регулярное выражение Java может сделать это с помощью Matcher#appendReplacement.   -  person Wiktor Stribiżew    schedule 08.12.2016
comment
comment
См. ideone.com/VPn2wl (в регулярном выражении верхнего комментария я забыл убрать точку).   -  person Wiktor Stribiżew    schedule 08.12.2016
comment
@WiktorStribiżew Большое спасибо, это решает множество других проблем, которые у меня есть. Как только я протестирую его с re2J, и если он будет работать хорошо, я дам вам знать, вы можете указать это как ответ.   -  person Amogh Talpallikar    schedule 08.12.2016
comment
Амог, у вас было время опробовать мой подход? Работает ли это для вас?   -  person Wiktor Stribiżew    schedule 05.06.2018


Ответы (2)


Обычный «трюк», когда вам нужно «пропустить» какое-то совпадение и заменить другим, состоит в том, чтобы сопоставить и захватить то, что вам нужно, и просто сопоставить то, что вам не нужно. Поскольку шаблон замены отличается для обоих контекстов, вы должны иметь возможность анализировать объект соответствия и Matcher#appendReplacement предоставляет следующую функциональность:

 String s = "[email protected]\ndomain.com\nwww.domain.com\nhttp://www.domain.com\nhttps://www.domain.com";
StringBuffer result = new StringBuffer();
Matcher m = Pattern.compile("(?i)\\S+@\\S+\\.\\S+|((?:https?://)?(?:[a-z0-9-]+[.])*[a-z0-9-]+[.][a-z]+/?[^\\s()<>]*)").matcher(s);
while (m.find()) {
    if (m.group(1) != null) {
        m.appendReplacement(result, "<a href=\"" + m.group(1) + "\">" + m.group(1) + "</a>");
    }
    else {
        m.appendReplacement(result, m.group());
    }
}
m.appendTail(result);
System.out.println(result.toString()); // Demo output

Демонстрация Java в Интернетеjava.util.regex, использующим тот же метод)

Сведения о шаблоне:

  • \\S+@\\S+\\.\\S+ — соответствует чему-то похожему на электронное письмо (1+ без пробелов, @, 1+ без пробелов, . и снова 1+ без пробелов)
  • | - or
  • ((?:https?://)?(?:[a-z0-9-]+[.])*[a-z0-9-]+[.][a-z]+/?[^\\s() <>]*) - Группа 1 фиксирует ваш паттерн.

Если группа 1 совпадает, это не null, и нам нужно заключить ее в тег. В противном случае просто вставьте всю спичку обратно.

person Wiktor Stribiżew    schedule 08.12.2016

Для [email protected] регулярное выражение будет просто сопоставлять e как [^@] и xample.com как остальную часть совпадения — позже они будут объединены в одно совпадение. Просто проверьте наличие пробелов перед URL-адресом, но не включайте его в подшаблон.

Посмотрите, это может вам помочь. preg_match_all, чтобы найти все URL, но исключить электронную почту

person Jyoti Prakash    schedule 08.12.2016
comment
А что, если @@example.com нужно извлечь? Или URL в начале строки? - person Wiktor Stribiżew; 08.12.2016