Как удалить весь 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