Регулярное выражение для конкретного тега - PullRequest
2 голосов
/ 17 сентября 2008

Я работаю над регулярным выражением в проекте .NET, чтобы получить определенный тег. Я хочу сопоставить весь тег DIV и его содержимое:

<html>
   <head><title>Test</title></head>
   <body>
     <p>The first paragraph.</p>
     <div id='super_special'>
        <p>The Store paragraph</p>
     </div>
     </body>
  </head>

Код:

    Regex re = new Regex("(<div id='super_special'>.*?</div>)", RegexOptions.Multiline);


    if (re.IsMatch(test))
        Console.WriteLine("it matches");
    else
        Console.WriteLine("no match");

Я хочу соответствовать этому:

<div id="super_special">
   <p>Anything could go in here...doesn't matter.  Let's get it all</p>
</div>

Я думал, что . должен был получить все символы, но, похоже, возникли проблемы с возвратом каретки. Чего не хватает моему регулярному выражению?

Спасибо.

Ответы [ 11 ]

6 голосов
/ 17 сентября 2008

Пожалуйста, довольно, пожалуйста, сделайте себе огромную услугу: используйте парсер HTML для парсинга HTML. Шутки в сторону. Вот для чего они там.

HTML - это очень сложный язык. Неважно, как долго вы будете настраивать, возиться, исправлять, оттачивать свое регулярное выражение, всегда будет случаем, которого вам не хватает.

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

Но позвольте мне повторить: пожалуйста, используйте анализатор HTML. Каждый раз, когда кто-то использует Regexp для разбора HTML, котенок умирает ...

1 голос
/ 17 сентября 2008

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

У меня есть еще один совет: остерегайтесь жадности! Традиционно регулярные выражения являются жадными, что означает, что ваше регулярное выражение, вероятно, будет соответствовать этому:

<div id="super_special">
  I'm the wanted div!
</div>
<div id="not_special">
  I'm not wanted, but I've been caught too :(
</div>

Вам следует проверить наличие не жадного модификатора, чтобы ваше регулярное выражение прекратило сопоставлять текст в first вхождении </div>, а не last .

Кроме того, как уже говорили другие, рассмотрите возможность использования анализатора HTML вместо регулярных выражений. Это избавит вас от головной боли.

Редактировать: даже не жадное регулярное выражение также не будет работать должным образом, если вложено <div>! Еще одна причина, чтобы рассмотреть возможность использования анализатора HTML.

1 голос
/ 17 сентября 2008

У большинства языков есть какой-то способ сделать. соответствовать новым строкам:

  • В Java: Pattern.compile ("pattern", Pattern.MULTILINE);
  • В Perl и Ruby: / pattern / m
  • В VB: Regex.IsMatch (s, "pattern", RegexOptions.Multiline)

Как правило, использование регулярного выражения для сопоставления с XML / HTML не очень хорошая идея, поскольку теги XML / HTML могут быть вложенными, например:

  <div id="super_special">
     <div>Nothing</div>
     <p>Anything could go in here...doesn't matter.  Let's get it all</p>
  </div>

... здесь вы можете легко найти соответствие:

  <div id="super_special">
     <div>Nothing</div>

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

1 голос
/ 17 сентября 2008

Проблема в том, что. Метасимвол не соответствует символам новой строки по умолчанию. Вы должны использовать однострочный модификатор для достижения этой цели. В .NET вы можете использовать RegexOptions.SingleLine в качестве последнего параметра метода, который вы используете, или использовать модификатор непосредственно в шаблоне, например:

(?s)(<div id="super_special">.*?</div>)
1 голос
/ 17 сентября 2008

Зависит от языка. Если на python вы пропускаете флаг re.S, например так (чтобы удалить совпадение):

re.compile('<div id="super_special">.*?</div>',re.S).sub(your_html,'')

Подобные флаги существуют для других реализаций регулярных выражений, они называются «Однострочные» или «Многострочные» или что-то в этом роде.

Но НЕ ИСПОЛЬЗУЙТЕ REGEXPS ДЛЯ РАЗДЕЛЕНИЯ HTML . Это прямой путь к адскому обслуживанию. Используйте HTML-парсер, например Beautiful Soup. Проверьте эти ссылки на наличие полезных ресурсов в этом направлении.

1 голос
/ 17 сентября 2008

Какой язык вы используете? В .NET вы должны установить опцию, чтобы убедиться, что это не одна строка.

1 голос
/ 17 сентября 2008

Зависит от того, на каком языке вы работаете. Например, в Perl вы бы использовали модификатор regex s:

m{<div id="super_special">.*?</span>}s
0 голосов
/ 21 сентября 2008

Регулярные выражения сами по себе недостаточно эффективны для решения вашей проблемы. Вам нужно что-то более мощное, например, контекстно-свободные грамматики. См. иерархия Хомского в Википедии.

Другими словами (как уже было сказано ранее), не используйте регулярные выражения для разбора HTML.

0 голосов
/ 17 сентября 2008

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

Регулярные выражения на самом деле не идеальный инструмент для этой цели, но если ваша ситуация достаточно проста, и вы не хотите анализировать HTML, вы можете сделать это, используя проприетарное расширение Microsoft для регулярного выражения, доступное в .NET , Хорошее объяснение см. В этой замечательной статье Мортена Мэйта .

0 голосов
/ 17 сентября 2008

возможно:. [\ r \ n] . [\ r \ n]

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