Regex виберіть весь текст між тегами


143

Який найкращий спосіб виділити весь текст між двома тегами - наприклад: текст між усіма попередніми тегами на сторінці.


2
Найкращий спосіб - використовувати HTML-аналізатор на кшталт "Красивий суп", якщо ви потрапили в пітон ...
Фредрік Піль

1
Найкращий спосіб - використовувати XML / HTML-аналізатор.
Даніель О'Хара

4
Загалом, з допомогою регулярних виразів для розбору HTML не є гарною ідеєю: stackoverflow.com/questions/1732348 / ...
murgatroid99

Не розбирайте текст між тегами з регулярним виразом, оскільки довільно вкладені теги роблять HTML нерегулярним. Відповідні теги, здається, добре. /<div>.*?<\/div>/.exec("<div><div></div></div>")
jdh8

Відповіді:


157

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

Як запропонували інші коментатори, якщо ви робите щось складне, використовуйте HTML-аналізатор.


41
При цьому не вибирається текст між тегами, він включає теги.
capikaw

3
Вам потрібно схопити вибір за допомогою ()
Саху V Кумар

2
Для багаторядкових тегів: <html_tag> (. +) ((\ S) + (. +)) + <\ / Html_tag>
Феліпе Аугусто

Це все ще має видимість, тому: Якщо ви все ще бачите <pre>теги після спроби <pre>(.*?)<\/pre>, це тому, що ви дивитесь на те, що було захоплено повним збігом замість групи захоплення (. *?). Звучить симпатично, але я завжди думаю, що «кругла дужка = пара злодіїв», тому що якщо не (буде супроводжуватись ?як в, (?:або (?>кожен матч матиме два захоплення: 1 для повного матчу та 1 для групи захоплення. Кожен додатковий набір дужок додає додаткове захоплення. Ви просто повинні знати, як отримати обидва знімки будь-якою мовою, з якою ви працюєте.
rbsdca

137

Тег можна заповнити в іншому рядку. Ось чому \nпотрібно додати.

<PRE>(.|\n)*?<\/PRE>

5
Важливий момент щодо додавання (.|\n)*?під час роботи з тегами HTML у кількох рядках. Вибрана відповідь працює лише в тому випадку, якщо теги HTML знаходяться в одному рядку.
Caleuanhopkins

3
<PRE> (. | \ N | \ r \ n) *? <\ / PRE> для закінчень рядків Windows
Марк

3
Ніколи не використовуйте, (.|\n)*?щоб відповідати жодним знакам Завжди використовуйте .з s(SingleLine) модифікатора. Або [\s\S]*?вирішення проблеми.
Wiktor Stribiżew

Я хотів вибрати коментарі до коду в блокноті ++, тому, використовуючи цю відповідь, я придумав, /\*(.|\n)*?\*/що зробив роботу - дякую
wkille

ідеальна відповідь велике спасибі
Омда

25

Це я б використовував.

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

В основному це:

(?<=(<pre>))Вибір повинен бути доповнений <pre>тегом

(\w|\d|\n|[().,\-:;@#$%^&*\[\]"'+–/\/®°⁰!?{}|~]| )Це просто регулярний вираз, який я хочу застосувати. У цьому випадку в квадратних дужках він вибирає літеру чи цифру чи новий рядок або деякі спеціальні символи, наведені у прикладі. Характер труби |просто означає " АБО ".

+?Плюс символьних станів, щоб вибрати одне або декілька вищезазначених - порядок не має значення. Знак питання змінює поведінку за замовчуванням з "жадібної" на "недоброзичливу".

(?=(</pre>))Вибір має бути доданий </pre>тегом

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

Залежно від випадку використання, можливо, вам доведеться додати деякі модифікатори, такі як ( i або m )

  • i - нечутливі до регістру
  • m - багаторядковий пошук

Тут я здійснив цей пошук у Sublime Text, тому мені не довелося використовувати модифікатори в моєму регексе.

Javascript не підтримує погляд позаду

Наведений вище приклад повинен добре працювати з такими мовами, як PHP, Perl, Java ... Однак JavaScript не підтримує відставання, тому нам потрібно забути про використання (?<=(<pre>))та шукати якесь вирішення. Можливо, просто зніміть перші чотири символи від нашого результату для кожного вибору, як тут у тексті Regex відповідності між тегами

Також дивіться ДОКУМЕНТАЦІЮ JAVASCRIPT REGEX щодо невлаштованих дужок


Зауважте, що вам потрібно уникнути символів одинарних / подвійних цитат за допомогою `для того, щоб помістити регулярний параметр в рядок.
Девід Зварт

18

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

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

Колись теги матимуть атрибути, як anchorтег href, а потім скористайтеся наведеною нижче схемою.

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

Спробуйте перший приклад як "<head> (. +?) </head>" і працює так, як очікувалося. Але у мене немає результатів із другим.
Алекс Беррт

1
це не працює. <[tag]>буде відповідати <t>, <a>і<g>
Martin Schneider

2
@ MA-Maddin - Я думаю, ви пропустили цю Replace [tag] with the actual element you wish to extract the content fromчастину.
LWC

2
О так, так. Їх []слід було взагалі пропустити. Це було б зрозуміліше, через їх значення в RegEx і те, що люди спочатку сканують код і читають текст після;)
Мартін Шнайдер

14

Щоб виключити розмічувальні теги:

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

(?<=<pre>) шукає текст після <pre>

(?=</pre>) шукає текст раніше </pre>

Результати будуть містити текст всередині preтегу


Люди, які використовують цей погляд, дивляться на відповідь @krishna thakor, яка також може врахувати, чи вміст має новий рядок між тегами
KingKongCoder

Це допомогло в моєму випадку (не потрібно розглядати нові рядки). Дякую.
Пікінг

6

Вам не слід намагатися розібрати 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();

А оскільки це правильний аналізатор, він зможе обробляти вкладені теги тощо.


2
Просто хочу сказати, що я трохи занепокоєний тим, що це все ще збирає зворотний зв'язок, хоча це єдина відповідь, яка забезпечує правильне рішення поруч з регулярним виразком, і я також додав достатньо попередження, що це, мабуть, не правильний шлях ... Принаймні, прокоментуйте, будь ласка, що так неправильно у моїй відповіді.
sg3s

1
Питання не було позначене php. Не впевнений, як PHP увійшов у світлину ...
trincot

@trincot Це було більше 7 років тому, тому я не можу згадати. У будь-якому випадку це приклад вирішення проблеми з регулярним виразом та з аналізатором. Регекс хороший, а php - це саме те, що я добре знав у той час.
sg3s

Я розумію, я побачив ваш перший коментар і подумав, що це може пояснити деякі суті.
трінкот


4

Здається, це найпростіший регулярний вираз із усіх, що я знайшов

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

3

Ця відповідь передбачає підтримку огляду навколо! Це дозволило мені визначити весь текст між парами тегів, що відкриваються та закриваються. Це весь текст між '>' та '<'. Це працює, тому що при огляді не використовуються символи, які йому відповідають.

(? <=>) ([\ 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. Удача.


Дякую. Це не тільки краща відповідь, але і чудове посилання на сайт regex101. Оголошено! 🙂
Шон Фельдман

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)цей регулярний вибір буде вибирати все між тегом. незалежно від того, що це в новому рядку (робота з багаторядковим.


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

Я використовую це рішення:

preg_match_all( '/<((?!<)(.|\n))*?\>/si',  $content, $new);
var_dump($new);

-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>

6
Будь ласка, введіть / поясніть свою відповідь словами.
Ендрю Реган
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.