разбирать URL-адрес из строки в Coldfusion - PullRequest
2 голосов
/ 15 июля 2010

мне нужно разобрать все URL из абзаца (строки)
например.

"зайдите на этот сайт google.com и не забудьте посмотреть это тоже bing.com/maps"

должно возвращаться "google.com and bing.com/maps"

В настоящее время я использую это, и это не до совершенства.

reMatch("(^|\s)[^\s@]+\.[^\s@\?\/]{2,5}((\?|\/)\S*)?",mystring)

спасибо

1 Ответ

5 голосов
/ 15 июля 2010

Вам нужно более четко определить, что вы считаете 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.

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