Удалите теги и замените все теги br и p одним пробелом

Что такое регулярное выражение для удаления всех тегов html и где есть теги <br> и <p>, заменить их одним пробелом и удалить все разрывы строк?

например:

<h1>Heading</h1>
<br>
<br />
<a href = "#">hyperlink</a>
<p></p>
<p>paragraph1</p>
<p>paragraph2</p>

Должно стать:

Heading hyperlink paragraph1 paragraph2

Я пробовал следующее:

$string = preg_replace( ["/<br\s*/?>/i","/</p\s*>/i"]," ",$string);
$string = preg_replace(["/</?[^>]+>/", "/\r?\n|\r/"],"",$string);

Что дает мне:

Heading              hyperlink         paragraph1 paragraph2 

любые идеи одной линии или более элегантного решения, которое действительно работает?

@Nahiyan, я хочу удалить ВСЕ html. Вышеупомянутое было просто примером.

adam78 28.12.2018 18:00

Вы пробовали что-то вроде этого: "preg_replace (" / <h1> | <p> | </p> | </h1> / g "," ", $ string)"?

Nahiyan 28.12.2018 18:01

Что насчет этого? preg_replace ("/ <[^>] * [/] *> / g", "", $ string);

Nahiyan 28.12.2018 18:03

Regex - не лучший способ справиться с этим. Вы должны использовать DomDocument для перебора тегов и получения их значений innerHTML, добавления пробелов и т. д.

nice_dev 28.12.2018 18:15

@ vivek_23 то, что вы предлагаете, излишне. Все, что я хочу сделать, это удалить весь html и вывести однострочную строку. Там, где есть теги br и p, мне нужно заменить одним пробелом, и если есть какие-либо разрывы строк, их необходимо удалить

adam78 28.12.2018 18:19

@ adam78, это не перебор. Это решение. Regex не даст вам правильных ответов, если вы не полностью контролируете, какой HTML у вас будет.

nice_dev 28.12.2018 18:28
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
0
6
1 267
6
Перейти к ответу Данный вопрос помечен как решенный

Ответы 6

Вы можете сгруппировать несколько тегов, окруженных пробелами, и заменить их одним пробелом. Заменяемое регулярное выражение будет таким:

(\s*<[^>]+>\s*)+

Это даст вам единый пробел вместо всех этих тегов и, наконец, используйте trim(), чтобы избавиться от крайнего правого и левого пробелов, которые могут вам не понадобиться.

Демо

Вот PHP-код для демонстрации,

$html = '<h1>Heading</h1>
<br>
<br />
<a href = "#">hyperlink</a>
<p></p>
<p>paragraph1</p>
<p>paragraph2</p>';

echo trim(preg_replace("/(\s*<[^>]+>\s*)+/", " ", $html));

Принты,

Heading hyperlink paragraph1 paragraph2

Что, если в innerHTML есть < и >?

nice_dev 28.12.2018 18:11

Как и хочет OP, даже этот внутренний тег будет удален. Хотя в целом html не следует манипулировать с помощью регулярных выражений, я предложил это, поскольку с этим можно справиться в случае OP. Отметьте здесь, где даже внутренние теги будут заменены пробелом с сохранением любого текста внутри тегов, если таковой имеется. Демо

Pushpesh Kumar Rajwanshi 28.12.2018 18:16

Я имею в виду контент вроде x < y and a > b.

nice_dev 28.12.2018 18:29

@ vivek_23: Вы когда-нибудь видели такие настоящие html-данные? Если только вы не создадите его искусственно :) Хотя я могу сделать свое регулярное выражение более жестким, если у OP есть такие данные для обработки. Вместо <[^>]+> он стал бы просто <\w[^>]*>

Pushpesh Kumar Rajwanshi 28.12.2018 18:31

И если у вас есть искаженные теги, такие как < sometag some attributes etc etc>, регулярное выражение можно изменить на <\s*\w[^>]*>, чтобы обработать лишнее пространство перед именем тега. Такие небольшие изменения всегда можно легко сделать, в зависимости от данных. Но если вы не знаете, какие данные будут там, на самом деле не стоит усложнять ваше регулярное выражение.

Pushpesh Kumar Rajwanshi 28.12.2018 18:38

Ну, это не обрезка. Таким образом, остается начальное и конечное пространство .... но неважно.

ArtisticPhoenix 28.12.2018 18:47

@ArtisticPhoenix: Я уже писал в своем посте, вы можете просто сделать trim($str), чтобы обрезать его.

Pushpesh Kumar Rajwanshi 28.12.2018 18:48

@PushpeshKumarRajwanshi Я согласен, и такие HTML-данные могут быть. Возьмем, к примеру, любой математический сайт. Эти символы могут быть написаны в его DOM для объяснения некоторых математических концепций и т. д. Более того, как вы сказали ранее, регулярное выражение никогда не является решением таких проблем, и я уверен, что OP введет в заблуждение многих будущих рефереров сообщений, чтобы использовать регулярное выражение для таких вещей.

nice_dev 28.12.2018 19:08

@ vivek_23: Я согласен с вами, что HTML никогда не следует анализировать с помощью регулярных выражений. Но одна из основных причин этого заключается в том, что HTML может содержать вложенные структуры, которые регулярное выражение не может обрабатывать. Но в случае OP нет вложенных тегов, и это даже не повлияло бы, если бы у него действительно были вложенные теги. Потому что все, чего хочет OP, - это избавиться от тегов. Таким образом, для этой конкретной задачи OP наверняка может написать одну строку кода для выполнения своей задачи. Таким образом, мудрость не всегда заключается в слепом следовании правилу, а в знании того, когда использовать, а когда нет. Но да, в общем случае регулярное выражение не следует использовать для HTML.

Pushpesh Kumar Rajwanshi 28.12.2018 19:16

Вы можете использовать это

<\s*/?\s*br[^>]*>|<\s*/?\s*p[^>]*>|\n

Explanation

  • <\s*/?\s*br[^>]*> - соответствует <br>, </br> или <br/> с любым количеством пробелов и также соответствует атрибутам.
  • <\s*/?\s*p[^>]*> - Соответствует <p>, </p> или <p/> с любым количеством пробелов, также соответствует атрибутам.
  • \n - соответствует новой строке.

Демо

Тег p может иметь атрибуты.

nice_dev 28.12.2018 18:12

@Code он не заменяет верхний регистр <Br>, а также не заменяет разрывы строк и все другие теги html

adam78 28.12.2018 18:12

@ adam78, вы можете включить для этого флаг нечувствительности к регистру. а для \n я обновил ответ

Code Maniac 28.12.2018 18:19

Вы можете оставить то, что у вас есть, удалить лишние пробелы

$stripped = preg_replace('/\s+/', ' ', $string);

Это возвращается:

Heading hyperlink paragraph1 paragraph2

все еще в конечном итоге и дополнительное пространство между hyperlink и paragraph1

adam78 28.12.2018 18:16
Ответ принят как подходящий

Вот что бы я сделал:

$a = '<h1>Heading</h1>
<br>
<br />
<a href = "#">hyperlink</a>
<p></p>
<p>paragraph1</p>
<p>paragraph2</p>';


echo trim(preg_replace(['/<[^>]*>/','/\s+/'],' ', $a));

Вывод

 Heading hyperlink paragraph1 paragraph2 

Песочница

Первое регулярное выражение удаляет теги, заменяя их пробелом, второе занимает несколько пробелов и заменяет их на один.

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

What is the regex to strip all html tags and where there are <br> and <p> tags replace with a single space and remove all line breaks

Итак, если вам нужно «полное» решение, вы можете сделать это:

$a = '<h1>Heading</h1>
<br>
<br />
<a href = "#">hyperlink</a>
<p></p>
<p><big>p</big>aragraph1</p><p>paragraph2</p>';

echo preg_replace([
    '/<(?:br|p)[^>]*>/i', //replace br p with ' '
    '/<[^>]*>/',  //replace any tag with ''
    '/\s+/', //remove run on space
    '/^\s+|\s+$/' //trim
],[
    ' ', '', ' ', ''
], $a);

Обратите внимание, что я добавил тег <big> и удалил все пробелы между тегами <p>. Это было сделано, чтобы выделить несколько моментов.

Например, если вы возьмете текст из второго примера и используете его в первом, вы получите это (из-за большого тега):

Heading hyperlink p aragraph1 paragraph2 

Обновленный пример выводит правильно. Но, и это большое «но», я изменил вводимый текст, поэтому, возможно, нет необходимости чрезмерно его усложнять.

Тег <p> просто показывает, что он ставит пробел между ними перед удалением всех тегов HTML с помощью ''.

Песочница

ОБНОВИТЬ

@ArtisticPhoenix how would I accomodate <p>&nbsp;</p>

Сначала я бы преобразовал строку с помощью html_entity_decode, но с этим есть несколько проблем. Это связано с кодированием. Итак, это правильный способ сделать это:

$a = '<h1>Heading</h1>
<br>
<br />
<a href = "#">hyperlink</a>
<p>&nbsp;</p>
<p><big>p</big>aragraph1</p><p>paragraph2</p>';

 //convert entities using UTF-8
$a = html_entity_decode($a, ENT_QUOTES, 'UTF-8');

echo preg_replace([
    '/<(?:br|p)[^>]*>/i', //replace br p with ' '
    '/<[^>]*>/',  //replace any tag with ''
    '/\s+/u', //remove run on space - replace using the unicode flag
    '/^\s+|\s+$/u' //trim - replace using the unicode flag
],[
    ' ', '', ' ', ''
], $a);

Обратите внимание на добавление флага u к регулярному выражению выше /\s+/u и /^\s+|\s+$/u.

u (PCRE_UTF8) This modifier turns on additional functionality of PCRE that is incompatible with Perl. Pattern and subject strings are treated as UTF-8. An invalid subject will cause the preg_* function to match nothing; an invalid pattern will trigger an error of level E_WARNING. Five and six octet UTF-8 sequences are regarded as invalid since PHP 5.3.4 (resp. PCRE 7.3 2007-08-28); formerly those have been regarded as valid UTF-8.

Проблема возникает из-за его декодирования в ASCII 160 (nbsp) вместо символа ASCII 32 (одиночный пробел). В любом случае мы можем использовать UTF-8, чтобы разобраться, как показано выше.

Песочница

@ArtisticPhoenix: Вы неправильно написали мое регулярное выражение. Вам не хватает + в регулярном выражении, которое я написал. В демонстрации песочницы вы используете (\s*<[^>]+>\s*) вместо моего регулярного выражения, которое является (\s*<[^>]+>\s*)+. Я думаю, что мое регулярное выражение достаточно простое и работает за один раз.

Pushpesh Kumar Rajwanshi 28.12.2018 18:41

Без шуток ... не заметил.

ArtisticPhoenix 28.12.2018 18:42

@ArtisticPhoenix: Все в порядке, дорогая. Но мое регулярное выражение работает и достаточно просто.

Pushpesh Kumar Rajwanshi 28.12.2018 18:42

@ArtisticPhoenix: Твое тоже правильно, но разве мое не проще?

Pushpesh Kumar Rajwanshi 28.12.2018 18:47

@PushpeshKumarRajwanshi - нет. У вас просто неполное регулярное выражение, в котором отсутствуют разделители. Мой - это настоящий исполняемый код, который начинающий программист может вставить прямо во что-то и начать с ним работать. Они должны выяснить несколько вещей. Если вы действительно хотите сравнить, мы можем. Но, честно говоря, мне все равно.

ArtisticPhoenix 28.12.2018 18:49

@ArtisticPhoenix: OP уже знает, как это сделать в кодах PHP, но тем не менее. Я также добавил в свой ответ примеры кодов php.

Pushpesh Kumar Rajwanshi 28.12.2018 18:52

@ArtisticPhoenix, как мне разместить <p>&nbsp;</p>?

adam78 28.12.2018 20:15

Сначала я бы использовал html_entity_decode на струне. Это лучший способ, если вы просто конвертируете его в текст, потому что он также исправит такие вещи, как амперсанд &amp; и &copy; или любые другие объекты html. Из-за замены рабочего места /\s+/ любое дополнительное пространство, добавленное путем преобразования неразрывного пространства, также будет сметено.

ArtisticPhoenix 28.12.2018 21:41

Это можно сделать с помощью двух шаблонов

P1: <[/\d\w]+.*?> который очистит все теги.

P2: [\n\s]+ и заменить его на одиночный пробел

Пример:

$string = preg_replace( "<[/\d\w]+.*?>","",$string);
$string = preg_replace("[\n\s]+"," ",$string);

Обработка HTML как строки и использование регулярных выражений - плохая идея. Единственное достойное решение, не использующее парсер DOM, - это использовать встроенную в PHP функцию strip_tags (которая использует a Государственный аппарат, поэтому по-прежнему уязвима для потенциальных проблем со сломанным HTML), а затем вы можете сжать полученный пробел с помощью регулярного выражения:

<?php
$html = '<h1>Heading</h1>
<br>
<br />
<a href = "#">hyperlink</a>
<p></p>
<p>paragraph1</p>
<p>paragraph2</p>';

echo preg_replace("/\s+/", " ", strip_tags($html));

Вывод:

Heading hyperlink paragraph1 paragraph2

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