Регулярное выражение для конкретного тега
Я работаю над регулярным выражением в .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 ответов
Готовые, без специальных модификаторов, большинство реализаций регулярных выражений не выходят за пределы конца строки, чтобы соответствовать тексту. Вам, вероятно, следует обратиться к документации движка регулярных выражений, который вы используете для такого модификатора.
У меня есть еще один совет: остерегайтесь жадности! Традиционно регулярное выражение является жадным, что означает, что ваше регулярное выражение, вероятно, будет соответствовать этому:
<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>
Вам следует проверить наличие не жадного модификатора, чтобы ваше регулярное выражение прекратило сопоставлять текст при первом появлении </div>
не на последнем.
Также, как уже говорили другие, рассмотрите возможность использования анализатора HTML вместо регулярных выражений. Это избавит вас от головной боли.
Изменить: даже не жадное регулярное выражение не будет работать, как ожидалось, если <div>
s вложены! Еще одна причина, чтобы рассмотреть возможность использования анализатора HTML.
Пожалуйста, сделайте себе огромное одолжение: используйте парсер HTML для парсинга HTML. Шутки в сторону. Вот для чего они здесь.
HTML это очень сложный язык. Независимо от того, как долго вы будете дорабатывать, возиться, исправлять, оттачивать свое регулярное выражение, всегда будет случай, которого вам не хватает.
В любом случае, вы должны указать вашему движку Regexp, чтобы он совпадал с несколькими строками вместо одной. В некоторых из самых популярных из них вы делаете это, применяя /m
модификатор.
Но позвольте мне повторить: пожалуйста, используйте анализатор HTML. Каждый раз, когда кто-то использует Regexp для разбора HTML, котенок умирает...
Какой язык вы используете? В.NET вы должны установить опцию, чтобы убедиться, что это не одна строка.
Зависит от языка. Если на python вы пропускаете флаг re.S, например так (чтобы удалить совпадение):
re.compile('<div id="super_special">.*?</div>',re.S).sub(your_html,'')
Подобные флаги существуют для других реализаций регулярных выражений, они называются "Однострочные" или "Многострочные" или что-то в этом роде.
Но НЕ ИСПОЛЬЗУЙТЕ REGEXPS ДЛЯ РАЗДЕЛЕНИЯ HTML Это прямой путь к аду обслуживания. Используйте HTML-парсер, например Beautiful Soup. Проверьте эти ссылки на полезные ресурсы в этом направлении.
Зависит от того, на каком языке вы работаете. Например, в perl вы бы использовали модификатор regex s:
m{<div id="super_special">.*?</span>}s
Проблема в том, что. Метасимвол не соответствует символам новой строки по умолчанию. Вы должны использовать однострочный модификатор для достижения этой цели. В.NET вы можете использовать RegexOptions.SingleLine в качестве последнего параметра метода, который вы используете, или использовать модификатор непосредственно в шаблоне, например:
(?s)(<div id="super_special">.*?</div>)
У большинства языков есть какой-то способ сделать. соответствовать новым строкам:
- В Java: Pattern.compile("шаблон", 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-код всегда будет безопасен для вашего регулярного выражения, не позволяйте мне останавливать вас (хотя даже тогда вам следует дважды подумать о том, чтобы спасти свое будущее от потенциальной отладки). Головная боль).
, (точка) Соответствует любому одному символу, кроме символов разрыва строки \r и \n. У большинства разновидностей регулярных выражений есть опция, позволяющая сделать точку с символом разрыва строки., соответствует x или (почти) любому другому символу
Ни одно из этих предложений не сработает. В зависимости от того, жадные они или нет, они будут соответствовать либо самому последнему div> в документе, либо самому первому div> после вашей начальной строки, которая может быть вложенной в ту, в которую вы попали увлекающийся.
Регулярные выражения на самом деле не идеальный инструмент для этой цели, но если ваша ситуация достаточно проста, и вы не хотите анализировать HTML, вы можете сделать это, используя проприетарное расширение Microsoft для регулярных выражений, доступное в.NET. Хорошее объяснение смотрите в этой хорошей статье Мортена Мэйта.
Регулярные выражения сами по себе недостаточно эффективны для решения вашей проблемы. Вам нужно что-то более мощное, например, контекстно-свободные грамматики. См. Иерархию Хомского в Википедии.
Другими словами (как уже было сказано ранее), не используйте регулярные выражения для анализа HTML.