Как удалить весь HTML-тег (и его содержимое) по классу с помощью регулярного выражения?
Я не очень хорошо с Regex, но я учусь.
Я хотел бы удалить некоторый HTML-тег по имени класса. Это то, что у меня есть до сих пор :
<div class="footer".*?>(.*?)</div>
первый .*? потому что он может содержать другой атрибут, а во-вторых, он может содержать другие html-файлы.
что я делаю не так? Я попробовал много набора без успеха.
обновление
внутри DIV он может содержать несколько строк, и я играю с Perl регулярное выражение.
8 ответов
вы также захотите учесть другие вещи перед классом в теге div
<div[^>]*class="footer"[^>]*>(.*?)</div>
кроме того, идите без учета регистра. Вам может потребоваться избежать таких вещей, как кавычки или косая черта в закрывающем теге. В каком контексте вы это делаете?
также обратите внимание, что синтаксический анализ HTML с регулярными выражениями может быть очень неприятным, в зависимости от ввода. Хороший момент приведен в ответе ниже-предположим, у вас есть структура, подобная:
<div>
<div class="footer">
<div>Hi!</div>
</div>
</div>
попытка построить regex для этого-рецепт катастрофы. Лучше всего загрузить документ в DOM и выполнить манипуляции с ним.
псевдокод, который должен сопоставляться с XML:: DOM:
document = //load document
divs = document.getElementsByTagName("div");
for(div in divs) {
if(div.getAttributes["class"] == "footer") {
parent = div.getParent();
for(child in div.getChildren()) {
// filter attribute types?
parent.insertBefore(div, child);
}
parent.removeChild(div);
}
}
Вот библиотека perl,HTML:: DOM, и еще XML:: DOM
.NET имеет встроенные библиотеки для обработки синтаксического анализа dom.
как говорили другие люди, HTML, как известно, сложно справиться с использованием регулярных выражений, и подход DOM может быть лучше. Например:
use HTML::TreeBuilder::XPath;
my $tree = HTML::TreeBuilder::XPath->new;
$tree->parse_file( 'yourdocument.html' );
for my $node ( $tree->findnodes( '//*[@class="footer"]' ) ) {
$node->replace_with_content; # delete element, but not the children
}
print $tree->as_HTML;
в Perl вам нужно /s
модификатор, иначе точка не будет соответствовать новой строке.
тем не менее, использование правильного парсера HTML или XML для удаления нежелательных частей HTML-файла гораздо более уместно.
частично зависит от точного механизма регулярных выражений, который вы используете-какой язык и т. д. Но одна из возможностей заключается в том, что вам нужно избежать кавычек и/или косой черты. Вы также можете сделать его нечувствительным к регистру.
<div class=\"footer\".*?>(.*?)<\/div>
в противном случае, пожалуйста, скажите, какой язык/платформа вы используете - .NET, java, perl ...
попробуйте это:
<([^\s]+).*?class="footer".*?>([.\n]*?)</([^\s]+)>
вашей самой большой проблемой будут вложенные теги. Например:
<div class="footer"><b></b></div>
данное регулярное выражение будет соответствовать все, через </b>
, оставив </div>
болтается на конце. Вам придется либо предположить, что тег, который вы ищете, не имеет вложенных элементов, либо вам нужно будет использовать какой-то парсер из HTML в DOM и запрос XPath для удаления всего под-дерева.
это будет сложно из-за жадности регулярных выражений (обратите внимание, что мои примеры мая быть конкретным для perl, но я знаю, что жадность является общей проблемой с REs.) Второй .*?
будет соответствовать как можно больше перед </div>
, поэтому, если у вас есть следующее:
<div class="SomethingElse"><div class="footer"> stuff </div></div>
выражение будет соответствовать:
<div class="footer"> stuff </div></div>
что вряд ли то, что вы хотите.
<div[^>]*class="footer"[^>]*>(.*?)</div>
работал для меня, но нужно использовать обратные слэши перед специальными символами
<div[^>]*class=\"footer\"[^>]*>(.*?)<\/div>
почему <div class="footer".*?</div>
Я тоже не гуру регулярных выражений, но я не думаю, что вам нужно указывать эту последнюю скобку для вашего открытого тега div