Задание Regex: сопоставлять фразу только если вне тега <a href> - PullRequest
0 голосов
/ 13 октября 2009

Я работаю над улучшением наших функций глоссария в пользовательской CMS, работающей с классическим ASP (ASP 3.0) на IIS с кодом VBScript. Я нахожусь в тупике перед проблемой регулярного выражения, которую не могу решить.

Вот текущий код:

     If InStr(ART_ArticleBody, "href") = False then
   sql="SELECT URL, Term, RegX FROM GLOSSARYDB;"
   Set rsGlossary = Server.CreateObject("ADODB.Recordset")
   rsGlossary.open sql, strSQLConn
   Set RegExObject = New RegExp
      While Not rsGlossary.EOF
      URL = rsGlossary("URL")
      Phrase = rsGlossary("RegX")
      With RegExObject
     .Pattern = Phrase
     .IgnoreCase = true
     .Global = false
      End With
      set expressionmatch = RegExObject.Execute(ART_ArticleBody)
      if expressionmatch.count > 0 then
      For Each expressionmatched in expressionmatch
      RegExObject.Pattern = Phrase
      URL = "<a href=" & URL & ">"& expressionmatched.Value & "</a>"
     ART_ArticleBody = RegExObject.Replace(ART_ArticleBody, URL)
      next
      end if
      rsGlossary.movenext
      wend
      rsGlossary.movefirst
   Set RegExObject = nothing
  end if

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

Например, курсивом ниже приведен тестовый пример для этой записи регулярного выражения в моей БД: ROI|return on investment|investment return

Вот ссылка, использующая термин глоссарий: <a href="ROI.htm">Info on return on investment</a>. Теперь вот глоссарий в виде простого текста, а не внутри ссылки: return on investment. Мы хотим найти третий экземпляр соответствия, но не находим первые два, потому что они оба находятся внутри HTML-ссылки.

В приведенном выше тексте, если бы я обрабатывал статью для записи глоссария «ROI | возврат инвестиций | возврат инвестиций», я не хочу совпадать с первым или вторым совпадением, поскольку они находятся в теге. Мне нужен шаблон регулярных выражений, чтобы пропустить эти совпадения и просто сопоставить их с любыми тегами, не входящими в тег.

Любая помощь по этому вопросу будет принята с благодарностью.

Ответы [ 5 ]

1 голос
/ 13 октября 2009

Попробуйте это регулярное выражение:

<a\b[^<>]*>[\s\S]*?</a>|(ROI|return on investment|investment return)

Это соответствует привязке HTML или любому из условий, которые вы ищете. Термины включены в группу номер 1. Поэтому в своем коде VBScript проверьте, соответствует ли первая группа захвата чему-либо, и у вас есть одно из ваших ключевых слов вне тега .

Это регулярное выражение действительно не будет работать правильно, если вы вложили теги . Это не должно быть проблемой, так как якоря обычно не вложены друг в друга. Если это проблема, вы не можете решить ее с помощью регулярных выражений VBScript / JavaScript. Регулярное выражение также не будет работать правильно, если у вас есть теги, в которых отсутствуют закрывающие теги. Если вы хотите принять это во внимание, попробуйте следующее регулярное выражение:

<a\b[^<>]*>(?:(?:(?!<a\b)[\s\S])*?</a>)?|(ROI|return on investment|investment return)
1 голос
/ 13 октября 2009

Эта проблема, как говорится, «нетривиальна» в своем нынешнем состоянии. Однако, если бы вы могли изменить свою систему для вывода более семантической разметки, это значительно упростило бы задачу:

<a href="ROI.htm">undesired tag match</a>
This is <span class="tag">a tag</span>

В этом случае вы можете просто выполнить поиск:

(?<=<span class=\"tag\">)(phrase1|phrase2|phrase3)(?=</span>)

Или что-то более надежное

(?<=<span class=\"tag\">).+?(?=</span>)

Таким образом, вы можете легко сосредоточить свои поиски на данных в пределах определенного <span> и оставить все остальное в стороне.

0 голосов
/ 13 октября 2009
(accounts receivable|A/R)(?!((?!</?a\b).)*</a)

(phrase1|phrase2|phrase3)(?!((?!</?a\b).)*</a)

Вышеописанный подход работает, по крайней мере, в моем программном обеспечении RegexBuddy Я не понял это самостоятельно. Была некоторая помощь от гуру. Время проверить это в моем коде ASP. Спасибо всем, кто внес свой вклад. Я уверен, что я не описал то, что мне нужно, достаточно хорошо, чтобы вы могли прийти к вышеуказанному решению. Mea culpa.

0 голосов
/ 13 октября 2009

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

Сказав это, .NET действительно предлагает расширение для регулярных выражений, которое делает невозможным то, что я только что сказал, и - что еще лучше! - образец главы для великолепного "Освоения регулярных выражений", доступной здесь случается, чтобы покрыть эту функцию.

0 голосов
/ 13 октября 2009

Вы не можете решить это, потому что это не может быть сделано, по крайней мере, не со 100% надежностью. HTML не является «регулярным» языком в смысле регулярных выражений. Как говорится, когда у тебя молоток, все начинает выглядеть как гвоздь. Есть некоторые вещи, в которых регулярные выражения не очень хороши. Это один из них.

Большинство языков имеют некоторую форму библиотеки разбора HTML как стандартную или легко доступную. Используйте те. Вот для чего они были созданы.

...