Регулярное выражение для удаления условных комментариев

Мне нужно регулярное выражение, которое может соответствовать условным комментариям на исходной странице HTML, поэтому я могу удалить только их. Хочу сохранить регулярные комментарии.

Я также хотел бы избежать использования. *? обозначения, если возможно.

Текст

foo

<!--[if IE]>

<style type = "text/css">

ul.menu ul li{
    font-size: 10px;
    font-weight:normal;
    padding-top:0px;
}

</style>

<![endif]-->

bar

и я хочу удалить все в <!--[if IE]> и <![endif]-->

Обновлено: Я хочу удалить эти теги из-за BeautifulSoup. BeautifulSoup не выполняет синтаксический анализ и предоставляет неполный исходный код

РЕДАКТИРОВАТЬ2: [если IE] - не единственное условие. Их гораздо больше, и у меня нет списка всех возможных комбинаций.

РЕДАКТИРОВАТЬ3: Решение Винко Врсаловича работает, но настоящая проблема, почему beautifulsoup не удалось, была связана с ложным комментарием в условном комментарии. Нравиться

<!--[if lt IE 7.]>
<script defer type = "text/javascript" src = "pngfix_253168.js"></script><!--png fix for IE-->
<![endif]-->

Заметили комментарий <!--png fix for IE-->?

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

Без .*? их нет, особенно если вы не знаете все возможные комбинации, как бы вы их все поймали без. * или подобного? А модификатор non-greedy нужен, если условных комментариев больше одного ...

Vinko Vrsalovic 25.09.2008 15:17

@Vinko Vrsalovic: Вы можете выполнить предварительное сопоставление, чтобы предотвратить. *? использование: regular-expressions.info/lookaround.html

Huppie 25.09.2008 15:47

Почему вы хотите избегать не жадных. *? построить?

Ben Doom 25.09.2008 17:26
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
5
3
4 773
7

Ответы 7

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

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

Строго говоря, условные комментарии - это не HTML, а встроенный макроязык, который AFAIK не может быть вложенным. Так что регулярное выражение может работать.

JacquesB 25.09.2008 14:34

@Benoit

Малая коррекция (при включенной многострочности):

 "<!--\[if IE\]>.*?<!\[endif\]-->"

Вы читали часть «Я бы также хотел по возможности избегать использования нотации. *?»?

Huppie 25.09.2008 14:37

Это работает в Visual Studio 2005, где нет параметра диапазона строк:

\<!--\[if IE\]\>{.|\n}*\<!\[endif\]--\>

>>> from BeautifulSoup import BeautifulSoup, Comment
>>> html = '<html><!--[if IE]> bloo blee<![endif]--></html>'
>>> soup = BeautifulSoup(html)
>>> comments = soup.findAll(text=lambda text:isinstance(text, Comment) 
               and text.find('if') != -1) #This is one line, of course
>>> [comment.extract() for comment in comments]
[u'[if IE]> bloo blee<![endif]']
>>> print soup.prettify()
<html>
</html>
>>>     

python 3 с bf4:

from bs4 import BeautifulSoup, Comment
html = '<html><!--[if IE]> bloo blee<![endif]--></html>'
soup = BeautifulSoup(html, "html.parser")
comments = soup.findAll(text=lambda text:isinstance(text, Comment) 
               and text.find('if') != -1) #This is one line, of course
[comment.extract() for comment in comments]
[u'[if IE]> bloo blee<![endif]']
print (soup.prettify())

Если ваши данные путают BeautifulSoup, вы можете исправить перед этим или настроить парсер, среди других решений.

Обновлено: в соответствии с вашим комментарием вы просто изменяете лямбду, переданную на findAll, как вам нужно (я изменил ее)

Это было полезно, но я не хочу терять все теги комментариев. Только условные комментарии css.

cnu 25.09.2008 14:37

Вот что вам понадобится:

<!(|--)\[[^\]]+\]>.+?<!\[endif\](|--)>

Он отфильтрует все виды условных комментариев, в том числе:

<!--[if anything]>
    ...
<[endif]-->

и

<![if ! IE 6]>
    ...
<![endif]>

EDIT3: Vinko Vrsalovic's solution works, but the actual problem why beautifulsoup failed was because of a rogue comment within the conditional comment. Like

Notice the comment?

Though my problem was solve, I would love to get a regex solution for this.

Как насчет этого:

(<!(|--)\[[^\]]+\]>.*?)(<!--.+?-->)(.*?<!\[endif\](|--)>)

Замените это регулярное выражение, оставив \ 1 \ 4 (или $ 1 $ 4) в качестве замены. Я знаю, что есть. *? и. +? в нем смотрите мой комментарий к этому посту.

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

Huppie 25.09.2008 14:52

Я бы просто пошел с:

import re

html = """fjlk<wb>dsqfjqdsmlkf fdsijfmldsqjfl fjdslmfkqsjf<---- fdjslmjkqfs---><!--[if lt IE 7.]>\
<script defer type = "text/javascript" src = "pngfix_253168.js"></script><!--png fix for IE-->\
<![endif]-->fjlk<wb>dsqfjqdsmlkf fdsijfmldsqjfl fjdslmfkqsjf<---- fdjslmjkqfs--->"""

# here the black magic occurs (whithout '.')
clean_html = ''.join(re.split(r'<!--\[[^¤]+?endif]-->', html))

print clean_html

'fjlk<wb>dsqfjqdsmlkf fdsijfmldsqjfl fjdslmfkqsjf<---- fdjslmjkqfs--->fjlk<wb>dsqfjqdsmlkf fdsijfmldsqjfl fjdslmfkqsjf<---- fdjslmjkqfs--->'

Примечание: [^ ¤] будет соответствовать любому символу, кроме '¤'. Это действительно полезно, так как работает молниеносно, и этот символ можно найти на любой клавиатуре. Но хитрость в том, что набирать его действительно сложно (никто не наберет его по ошибке) и никто не использует его: это обычный символ денежного изобретения.

Однако, если вы не хотите использовать ¤, вы можете использовать chr (7) для генерации символа «системный звонок», который не печатается и не может быть найден на веб-странице ;-)

Спасибо, что заметили опечатку. Очевидно, я имел в виду ¤, общий знак валюты, а не ø, которая является обычной буквой.

e-satis 19.10.2013 12:02

"е-сатис", это здорово. Лучший ответ и для меня единственное решение! Более того, он сохранился 12 лет! :)

Apostolos 02.08.2020 14:44

На мой взгляд, вам нужно беспокоиться только о комментариях скрытый на нижнем уровне (тех, которые начинаются с <!--), и вам не нужно ничего сопоставлять, кроме слова if и пробела после него. Это должно делать то, что вы хотите:

"<!--\[if\s(?:[^<]+|<(?!!\[endif\]-->))*<!\[endif\]-->"

Этот беспорядок посередине призван удовлетворить ваше желание не использовать .*?, но я не думаю, что это того стоит. Подход .*? должен работать нормально, если вы скомпилируете регулярное выражение с установленным флагом Re.S или оберните его в (?s:...). Например:

"(?s:<!--\[if\s.*?<!\[endif\]-->)"

Другие вопросы по теме