Regex выделяет весь текст между тегами

150

Как лучше всего выделить весь текст между двумя тегами - например, текст между всеми предварительными тегами на странице.

Башепс
источник
2
Лучший способ - использовать html-парсер, такой как "Beautiful Soup", если вы увлекаетесь питоном ...
Фредрик Пил
1
Лучше всего использовать парсер XML / HTML.
Дэниел О'Хара
4
В общем, использование регулярных выражений для синтаксического анализа HTML - не лучшая идея: stackoverflow.com/questions/1732348/…
murgatroid99
Не выполняйте синтаксический анализ текста между тегами с помощью регулярного выражения, потому что произвольно вложенные теги делают HTML нестандартным. Соответствующие теги вроде бы в порядке. /<div>.*?<\/div>/.exec("<div><div></div></div>")
jdh8

Ответы:

160

Вы можете использовать "<pre>(.*?)</pre>"(заменив pre любым текстом, который хотите) и извлечь первую группу (для более конкретных инструкций укажите язык), но это предполагает упрощенное представление о том, что у вас очень простой и действительный HTML.

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

PyKing
источник
46
Это не выделяет текст между тегами, он включает теги.
capikaw 01
3
Вы должны захватить выделение с помощью ()
Саху В Кумар
2
Для многострочных тегов: <html_tag> (. +) ((\ S) + (. +)) + <\ / Html_tag>
Felipe Augusto
1
Это все еще имеет видимость, поэтому: если вы все еще видите <pre>теги после попытки <pre>(.*?)<\/pre>, это потому, что вы смотрите на то, что было захвачено с помощью полного совпадения, а не группы захвата (. *?). Звучит банально, но я всегда думаю, что «скобка = пара воров», потому что, если за символом не (следует « ?как в» (?:или (?>, каждое совпадение будет иметь два захвата: 1 для полного соответствия и 1 для группы захвата. Каждый дополнительный набор скобок добавляет дополнительный захват. Вам просто нужно знать, как получить оба захвата на любом языке, с которым вы работаете.
rbsdca 05
вам нужно сбежать /
phil123456
143

Тег можно заполнить другой строкой. Вот почему \nнужно добавить.

<PRE>(.|\n)*?<\/PRE>
Зак
источник
5
Важный момент о добавлении (.|\n)*?при работе с HTML-тегами в несколько строк. Выбранный ответ работает, только если HTML-теги находятся в одной строке.
Caleuanhopkins 01
3
<PRE> (. | \ N | \ r \ n) *? <\ / PRE> для окончаний строк Windows
Марк,
3
Никогда не используйте (.|\n)*?для соответствия любому символу. Всегда используйте модификатор .with s(однострочный). Или [\s\S]*?обходной путь.
Wiktor Stribiew
Я хотел выбрать комментарии к коду в блокноте ++, поэтому, используя этот ответ, я придумал, /\*(.|\n)*?\*/что выполнило свою работу - спасибо
wkille
26

Это то, что я бы использовал.

(?<=(<pre>))(\w|\d|\n|[().,\-:;@#$%^&*\[\]"'+–/\/®°⁰!?{}|`~]| )+?(?=(</pre>))

В основном, что он делает:

(?<=(<pre>))Выбор должен быть предварен <pre>тегом

(\w|\d|\n|[().,\-:;@#$%^&*\[\]"'+–/\/®°⁰!?{}|~]| )Это просто регулярное выражение, которое я хочу применить. В этом случае он выбирает букву, цифру или символ новой строки или некоторые специальные символы, перечисленные в примере в квадратных скобках. Символ вертикальной черты |означает просто « ИЛИ ».

+?Состояния плюса для выбора одного или нескольких из вышеперечисленных - порядок не имеет значения. Знак вопроса изменяет поведение по умолчанию с «жадного» на «не жадное».

(?=(</pre>))Выделение должно быть добавлено </pre>тегом

введите описание изображения здесь

В зависимости от вашего варианта использования вам может потребоваться добавить некоторые модификаторы, такие как ( i или m )

  • i - без учета регистра
  • м - многострочный поиск

Здесь я выполнил этот поиск в Sublime Text, поэтому мне не пришлось использовать модификаторы в моем регулярном выражении.

Javascript не поддерживает поиск назад

Приведенный выше пример должен нормально работать с такими языками, как PHP, Perl, Java ... Javascript, однако, не поддерживает ретроспективный просмотр, поэтому мы должны забыть об использовании (?<=(<pre>))и искать какое-то обходное решение. Возможно, просто удалите первые четыре символа из нашего результата для каждого выбора, как здесь, текст соответствия Regex между тегами

Также посмотрите ДОКУМЕНТАЦИЮ JAVASCRIPT REGEX, чтобы узнать о скобках без захвата.

DevWL
источник
Обратите внимание, что вам нужно экранировать символы одинарных / двойных кавычек с помощью `, чтобы поместить регулярное выражение в строку.
Дэвид Цварт
21

используйте шаблон ниже, чтобы получить содержимое между элементами. Замените [tag]фактическим элементом, из которого вы хотите извлечь содержимое.

<[tag]>(.+?)</[tag]>

Иногда теги будут иметь атрибуты, например, anchorтеги href, тогда используйте шаблон ниже.

 <[tag][^>]*>(.+?)</[tag]>
Шраван Рамамурти
источник
Попробуйте первый пример как «<head> (. +?) </head>» и работает как ожидалось. Но со вторым у меня нет результатов.
Alex Byrth
1
это не работает. <[tag]>будет соответствовать <t>, <a>и<g>
Мартин Шнайдер
2
@ MA-Maddin - я думаю, ты пропустил Replace [tag] with the actual element you wish to extract the content fromроль.
LWC 06
2
Ну да ладно. Их []следовало вообще опустить. Это было бы более понятно из-за их значения в RegEx и того факта, что люди сначала сканируют код, а затем читают текст;)
Мартин Шнайдер
17

Чтобы исключить теги-разделители:

(?<=<pre>)(.*?)(?=</pre>)

(?<=<pre>) ищет текст после <pre>

(?=</pre>) ищет текст перед </pre>

Результаты будут отображаться внутри preтега

Жан-Симон Коллар
источник
Люди, использующие это, смотрят на ответ @krishna thakor, который также может учитывать, есть ли в содержимом новая строка между тегами
KingKongCoder
Это помогло в моем случае (не нужно рассматривать новые строки). Спасибо.
Пкин
7

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

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

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

preg_match("/<([\w]+)[^>]*>(.*?)<\/\1>/", $subject, $matches);
$matches = array ( [0] => full matched string [1] => tag name [2] => tag content )

Лучше использовать парсер, такой как собственный DOMDocument, для загрузки вашего html, затем выбрать свой тег и получить внутренний html, который может выглядеть примерно так:

$obj = new DOMDocument();
$obj -> load($html);
$obj -> getElementByTagName('el');
$value = $obj -> nodeValue();

И поскольку это правильный парсер, он сможет обрабатывать теги вложенности и т. Д.

sg3s
источник
2
Просто хочу сказать, что меня немного беспокоит то, что это все еще собирает отрицательные голоса, хотя это единственный ответ, который предлагает правильное решение рядом с регулярным выражением, и я также добавил достаточное предупреждение, что это, вероятно, неправильный путь ... По крайней мере, прокомментируйте, что не так в моем ответе, пожалуйста.
sg3s
1
Вопрос не был помечен php. Не знаю, как PHP появился на свет ...
trincot
@trincot Это было более 7 лет назад, поэтому я не могу вспомнить. В любом случае это пример решения проблемы с регулярным выражением и с парсером. Регулярное выражение хорошее, а php - это то, что я хорошо знал в то время.
sg3s
Я так понимаю, я видел ваш первый комментарий и подумал, что это может объяснить некоторые отрицательные голоса.
trincot
5

Попробуй это....

(?<=\<any_tag\>)(\s*.*\s*)(?=\<\/any_tag\>)
Эриберто Ривера
источник
3
Обратите внимание, что просмотр назад не поддерживается в JavaScript.
allicarn
Ооо, конечно, но это регулярное выражение для Java. спасибо за вашу заметку.
Эриберто Ривера
5

Этот ответ предполагает поддержку осмотрительности! Это позволило мне идентифицировать весь текст между парами открывающих и закрывающих тегов. Это весь текст между '>' и '<'. Это работает, потому что при осмотре не используются совпадающие символы.

(? <=>) ([\ w \ s] +) (? = </)

Я протестировал его на https://regex101.com/, используя этот фрагмент HTML.

<table>
<tr><td>Cell 1</td><td>Cell 2</td><td>Cell 3</td></tr>
<tr><td>Cell 4</td><td>Cell 5</td><td>Cell 6</td></tr>
</table>

Это игра из трех частей: взгляд назад, содержание и взгляд вперед.

(?<=>)    # look behind (but don't consume/capture) for a '>'
([\w\s]+) # capture/consume any combination of alpha/numeric/whitespace
(?=<\/)   # look ahead  (but don't consume/capture) for a '</'

снимок экрана с regex101.com

Надеюсь, это послужит началом для 10. Удачи.

Клариус
источник
1
Спасибо. Это не только лучший ответ, но и отличная ссылка на сайт regex101. Проголосовали! 🙂
Шон Фельдман
4

Кажется, это самое простое регулярное выражение из всех, что я нашел

(?:<TAG>)([\s\S]*)(?:<\/TAG>)
  1. Исключить открывающий тег (?:<TAG>)из совпадений
  2. Включите ([\s\S]*)в совпадения любые пробельные или непробельные символы
  3. Исключить закрывающий тег (?:<\/TAG>)из совпадений
макдуни
источник
2

var str = "Lorem ipsum <pre>text 1</pre> Lorem ipsum <pre>text 2</pre>";
    str.replace(/<pre>(.*?)<\/pre>/g, function(match, g1) { console.log(g1); });

Поскольку принятый ответ не содержит кода javascript, поэтому добавляем следующее:

Шишир Арора
источник
1

preg_match_all(/<pre>([^>]*?)<\/pre>/,$content,$matches)это регулярное выражение будет выбирать все между тегами. независимо от того, находится ли он в новой строке (работа с multiline.

Кришна Тхакор
источник
1

В Python установка DOTALLфлага захватит все, включая символы новой строки.

Если был указан флаг DOTALL, он соответствует любому символу, включая новую строку. docs.python.org

#example.py using Python 3.7.4  
import re

str="""Everything is awesome! <pre>Hello,
World!
    </pre>
"""

# Normally (.*) will not capture newlines, but here re.DOTATLL is set 
pattern = re.compile(r"<pre>(.*)</pre>",re.DOTALL)
matches = pattern.search(str)

print(matches.group(1))

python example.py

Hello,
World!

Захват текста между всеми открывающими и закрывающими тегами в документе

finditerЭто полезно для захвата текста между всеми открывающими и закрывающими тегами в документе . В приведенном ниже примере <pre>в строке присутствуют три открывающих и закрывающих тега.

#example2.py using Python 3.7.4
import re

# str contains three <pre>...</pre> tags
str = """In two different ex-
periments, the authors had subjects chat and solve the <pre>Desert Survival Problem</pre> with a
humorous or non-humorous computer. In both experiments the computer made pre-
programmed comments, but in study 1 subjects were led to believe they were interact-
ing with another person. In the <pre>humor conditions</pre> subjects received a number of funny
comments, for instance: “The mirror is probably too small to be used as a signaling
device to alert rescue teams to your location. Rank it lower. (On the other hand, it
offers <pre>endless opportunity for self-reflection</pre>)”."""

# Normally (.*) will not capture newlines, but here re.DOTATLL is set
# The question mark in (.*?) indicates non greedy matching.
pattern = re.compile(r"<pre>(.*?)</pre>",re.DOTALL)

matches = pattern.finditer(str)


for i,match in enumerate(matches):
    print(f"tag {i}: ",match.group(1))

python example2.py

tag 0:  Desert Survival Problem
tag 1:  humor conditions
tag 2:  endless opportunity for self-reflection
Джон
источник
0

Ты можешь использовать Pattern pattern = Pattern.compile( "[^<'tagname'/>]" );

Амбриш Раджпут
источник
0

Я использую это решение:

preg_match_all( '/<((?!<)(.|\n))*?\>/si',  $content, $new);
var_dump($new);
Т. Тодуа
источник
-1

Для нескольких строк:

<htmltag>(.+)((\s)+(.+))+</htmltag>
Дилип
источник
-1

В Javascript (среди прочего) это просто. Он охватывает атрибуты и несколько строк:

/<pre[^>]*>([\s\S]*?)<\/pre>/
Джонатан
источник
-4
<pre>([\r\n\s]*(?!<\w+.*[\/]*>).*[\r\n\s]*|\s*[\r\n\s]*)<code\s+(?:class="(\w+|\w+\s*.+)")>(((?!<\/code>)[\s\S])*)<\/code>[\r\n\s]*((?!<\w+.*[\/]*>).*|\s*)[\r\n\s]*<\/pre>
user5988518
источник
6
Пожалуйста, представьте / объясните свой ответ словами.
Эндрю Риган