Вам нужно более четко определить, что вы считаете URL-адресом
Например, я мог бы использовать что-то вроде этого:
(?:https?:)?(?://)?(?:[\w-]+\.)+[a-z]{2,6}(?::\d+)?(?:/[\w.,-]+)*(?:\?\S+)?
(используйте с reMatchNoCase
илиplonk (?i)
впереди, чтобы игнорировать регистр)
, который разрешает использование только буквенно-цифровых символов, подчеркивания и дефиса в домене и частях пути, требует, чтобы TLD был только буквами, и только ищет числовые порты.
Может быть, это достаточно хорошо, или вам может понадобиться что-то, что ищет больше символов, или, возможно, вы хотите обрезать такие вещи, как кавычки, скобки и т. Д., В конце URL-адреса или что-то еще - это зависитв контексте того, что вы делаете, хотите ли вы ошибиться в связи с отсутствующими URL-адресами или обнаружением не-URL-адресов.(Я бы, вероятно, выбрал второе, а затем мог бы запустить дополнительный фильтр, чтобы проверить, является ли что-то URL-адресом, но это требует больше работы и может не потребоваться для того, что вы делаете.)
Во всяком случае, объяснение вышеприведенного выражения приведено ниже, надеюсь, с четкими комментариями, которые помогут ему разобраться.:) (Обратите внимание, что все группы не захватывают (?:
... )
, поскольку нам не нужны отдельные части.)
# PROTOCOL
(?:https?:)? # optional group of "http:" or "https:"
# SERVER NAME / DOMAIN
(?://)? # optional double forward slash
(?:[\w-]+\.)+ # one or more "word characters" or hyphens, followed by a literal .
# grouped together and repeated one or more times
[a-z]{2,6} # as many as 6 alphas, but at least 2
# PORT NUMBER
(?::\d+)? # an optional group made up of : and one or more digits
# PATH INFO
(?:/[\w.,-]+)* # a forward slash then multiple alphanumeric, underscores, or hyphens
# or dots or commas (add any other characters as required)
# in a group that might occur multiple times (or not at all)
# QUERY STRING
(?:\?\S+)? # an optional group containing ? then any non-whitespace
Обновление: Чтобы предотвратить сопоставление конечных адресов электронной почты, нам нужно использовать просмотр за спиной, чтобы перед URL-адресом у нас не было знака @ (или чего-либо еще нежелательного), нобез фактического включения этого предшествующего символа в совпадение.
Регулярное выражение CF равно Apache ORO , которое не поддерживает lookbehinds, но мы можем легко и просто использовать java.util.regex с компонент, который я создал , который поддерживает lookbehinds.
Использовать его так же просто, как:
<cfset jrex = createObject('component','jre-utils').init('CASE_INSENSITIVE') />
...
<cfset Urls = jrex.match( regex , input ) />
После createObject это должно быть похоже на использование встроенногоПерефразируем, но с небольшой разницей в синтаксисе и другим движком регулярных выражений под капотом.
(Если у вас возникли проблемы или вопросы с компонентом, дайте мне знать.)
Итак, если вы исключаете электронные письма из проблемы с соответствием URL:
Мы можем сделать (?<=
положительный )
или (?<!
отрицательный )
взгляд назад, в зависимости от того, хотим ли мы сказать "мы должныиметь это "или" у нас не должно быть этого ", например:
(?<=\s) # there must be whitespace before the current position
(?<!@) # there must NOT be an @ before current position
Для этого примера URL я бы расширил любой из этих примеров до:
(?<=\s|^) # look for whitespace OR start of string
или
(?<![@\w/]) # ensure there is not a @ or / or word character.
Оба будут работать (и могут быть расширены с помощью большего числа символов), но по-разному, так что это просто зависит от того, с каким методом вы хотите это сделать.
Поставьте тот, который вам нравитсяначало вашего выражения, и оно больше не должно совпадать с концом abcd@gmail.com, если я что-то не испортил.:)
Обновление 2:
Вот пример кода, который исключит любые адреса электронной почты из матча:
<cfset jrex = createObject('component','jre-utils').init('CASE_INSENSITIVE') />
<cfsavecontent variable="SampleInput">
check out this site google.com and don't forget to see this too bing.com/maps
this is an email@somewhere.com which should not be matched
</cfsavecontent>
<cfset FindUrlRegex = '(?<=\s|^)(?:https?:)?(?://)?(?:[\w-]+\.)+[a-z]{2,6}(?::\d+)?(?:/[\w.,-]+)*(?:\?\S+)?' />
<cfset MatchedUrls = jrex.match( FindUrlRegex , SampleInput ) />
<cfdump var=#MatchedUrls#/>
Убедитесь, что вы загрузили jre-utils.cfc из здесь и поместите в соответствующее место (например, в тот же каталог, в котором находится скрипт, выполняющий этот код).
Этот шаг необходим, поскольку конструкция (?<=
... )
не работает в регулярных выражениях CF.