RegEx: заменить все URL-адреса, которые не привязаны - PullRequest
1 голос
/ 31 августа 2011

Я пытаюсь заменить URL-адреса, содержащиеся в блоке HTML-кода, которые пользователи публикуют в старом веб-приложении, с соответствующими привязками (<A>) для этих URL-адресов.

Проблема в том, что URL-адреса могут быть уже «привязаны», что содержится в <A> элементах. Эти URL не должны быть заменены.

Пример:

  <a href="http://noreplace.com">http://noreplace.com</a>         <- do not replace
  <a href="http://noreplace.com"><u>http://noreplace.com</u></a>  <- do not replace
  <a href="...">...</a>http://replace.com                         <- replace

Как бы выглядело регулярное выражение, совпадающее только с «не привязанными URL»?

Я использую следующую функцию для замены на RegEx:

Function ReplaceRegExp(strString, strPattern, strReplace)

    Dim RE: Set RE = New RegExp

    With RE
        .Pattern = strPattern
        .IgnoreCase = True
        .Global = True
        ReplaceRegExp = .Replace(strString, strReplace)
    End With

End Function

Следующее не жадное регулярное выражение используется для форматирования URL UBB. Можно ли адаптировать это регулярное выражение для соответствия только тем, которые мне нужны?

' the double doublequote in the brackets is because
' double doublequoting is ASP escaping for doublequotes
strString = ReplaceRegExp(strString, "\[URL=[""]?(http|ftp|https)(:\/\/[\w\-_]+)((\.[\w\-_]+)+)([\w\-\.,@?^=%&:/~\+#]*[\w\-\@?^=%&/~\+#])?[""]?\](.*?)\[/URL\]", "<a href=""$1$2$3$5"" target=""_blank"">$6</a>")

Если это не удастся сделать с помощью RegEx, каким было бы решение в ASP Classic, с некоторым кодом или псевдокодом, пожалуйста? Однако я действительно хотел бы сохранить код простым с помощью дополнительной строки регулярного выражения, чем добавлять дополнительные функции в этот старый код.

Спасибо за ваши усилия!

Ответы [ 3 ]

2 голосов
/ 31 августа 2011

Ответ, который вы ищете, в отрицательном и положительном взгляде вперед и в прошлом

Эта статья дает довольно хороший обзор: http://www.regular -expressions.info / lookaround.html

Вот регулярное выражение, которое я сформулировал для вашего случая:

(?<!"|>)(ht|f)tps?://.*?(?=\s|$)

Вот некоторые примеры данных, с которыми я сопоставил:

#Matches
http://www.website.com
https://www.website.com
This is a link http://www.website.com that is not linked
This is a long link http://www.website.com/index.htm?foo=bar
ftp://www.website.com

#No Matches
<u>http://www.website.com</u>
<a href="http://www.website.com">http://website.com</a>
<a href="https://www.website.com">http://website.com</a>
<a href="http://www.website.com"><u>http://www.website.com</u></a>
<a href="ftp://www.website.com">ftp://www.website.com</a>

Вот разбивка того, чторегулярное выражение выполняет:

(?<!"|>) Отрицательный взгляд позади, убедившись, что следующему не соответствует "или>

(ht|f)tps?://.*? Это ищет http, https,или ftp и все, что следует за ним. Это также будет соответствовать ftps! Если вы хотите избежать этого, вы можете использовать (https?|ftp)://.*? вместо

(?=\s|$) Это положительный взгляд вперед, который соответствует пробелу или концуof line.

ДОПОЛНИТЕЛЬНЫЙ КРЕДИТ

(ht)?(?(1)tps?|ftp):// Это будет соответствовать http / https / ftp, но не ftps, это может быть немного излишним, если вы можете использовать (https?|ftp):// но это потрясающий пример использования if / else в регулярных выражениях.

2 голосов
/ 31 августа 2011

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

Вот если кому-то это может понадобиться:

Function Linkify(Text)

    Dim regEx, Match, Matches, patternURLs, patternAnchors, lCount, anchorCount, replacements

    patternURLs = "((http|ftp|https)(:\/\/[\w\-_]+)((\.[\w\-_]+)+)([\w\-\.,@?^=%&:/~\+#]*[\w\-\@?^=%&/~\+#])?)"
    patternAnchors = "<a[^>]*?>.*?</a>"

    Set replacements=Server.CreateObject("Scripting.Dictionary")

    ' Create the regular expression.
    Set regEx = New RegExp
    regEx.Pattern = patternAnchors
    regEx.IgnoreCase = True
    regEx.Global = True

    ' Do the search for anchors.
    Set Matches = regEx.Execute(Text)

    lCount = 0

    ' Iterate through the existing anchors and replace with a placeholder
    For Each Match in Matches
      key = "<#" & lCount & "#>"
      replacements.Add key, Match.Value
      Text = Replace(Text,Cstr(Match.Value),key)
      lCount = lCount+1
    Next

    anchorCount = lCount

    ' we now search for URls
    regEx.Pattern = patternURLs

    ' create anchors from URLs
    Text = regEx.Replace(Text, "<a href=""$1"">$1</a>")

    ' put back the originally existing anchors
    For lCount = 0 To anchorCount-1
        key = "<#" & lCount & "#>"
        Text = Replace(Text,key, replacements.Item(key))
    Next

    Linkify = Text

End Function
0 голосов
/ 31 августа 2011

Некоторые проблемы проектирования, которые вам придется обойти:

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

Если вы можете предположить (1) абсолютные URL-адреса с протоколами и (2) цитируемые атрибуты HTML и (3) люди будут иметь пробелы после URL-адреса и (4) вы придерживаетесь поддержки только базовых символов URL, вы можете просто искать URL-адреса не предшествует двойная кавычка.

Вот слишком простой пример для начала (непроверенный):

(?<!")((http|https|ftp)://[^\s<>])(?=\s|$)  replaced with <a href="$1">$1</a>

Часть [^\s<>] выше смешножадный, так что все самое интересное будет в настройке построения набора символов, который соответствует URL-адресам, которые набирают ваши пользователи. В вашем примере показан гораздо более сложный класс символов с \w плюс мешанина другихсветящиеся символы, так что вы можете начать там, если хотите.

...