Программирование, радиоэлектроника,
саморазвитие и частичка из моей жизни здесь...

Интересный нюанс с пробелами при чистке текстов функцией preg_replace

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

Задача состояла в том, чтобы очистить пустые абзацы в самом начале текста во множестве статей, поскольку эти абзацы там не нужны и портят общий вид статьи.

Содержание:

  1. Проводим исследование
  2. Поможет HEX-редактор
  3. Заключение

Проводим исследование

Для выполнения задачи по чистке кусков кода, представляющего пустые абзацы, я решил использовать регулярные выражения (RegExp) в PHP. Простой функцией замены подстроки здесь не обойтись, поскольку вариантов и комбинаций может быть много.

Вот некоторые варианты HTML кода, которые присутствовали в тексте и выводили пустые абзацы:

<p></p>
<p> </p>
<p>&nbsp;&nbsp;</p>
<p>&#160;</p>
<p>    </p>

Как видим, между тегами может быть пробел, может быть его HTML-код, а также может и вовсе не быть никакого символа. Чистка таких строчек кода в текстах выполнялась регулярным выражением:

$txt=preg_replace( '#^<p>(&nbsp;|s|&#160;)+</p>#is' , '' , $original_text );

Статьи которые содержали ненужные пустые абзацы избавились от пустот, но в некоторых пустые абзацы вначале все же остались, посмотрев исходный код HTML одной из таких статей я увидел следующее:

<p>  </p>

Странно... два тега и несколько пробелов, возможно что-то упущено. Запустил чистку приведенным выше регулярным выражением еще раз - ничего не изменилось.

Что же это за мистика? Скопировал этот кусок кода с пробелами в буфер обмена и забросил в конвертер Text->Hex (http://www.swingnote.com/tools/texttohex.php), получаю результат:

Hex Spaced:
3c 70 3e 20 20 20 20 20 3c 2f 70 3e

Не видно ничего необычного: "20" (x20) - это код обычного пробела, функция должна была очистить эту строчку.
Решил написать регулярное выражение конкретно для этого случая:

$txt=preg_replace( '#^<p>x20+</p>#is' , '' , $original_text );

Это регулярное выражение так и не очистило указанную строчку (не заменило на пустую) – пробелы окутанные двумя тегами остались на своем месте.

Возможно что при копировании текста из браузера в буфер обмена символы как-то конвертируются, нужно как-то это все проверить.

Поможет HEX-редактор

Для выяснения что же представляет из себя эта загадочная строчка кода с двумя тегами и пробелами, решил применить HEX-редактор.

Текст был сохранен в файл с помощью PHP-функции "file_put_contents". Для того, чтобы просмотреть текстовый файл в HEX-формате, пригодилась программа под названием "HxD".

HxD - это бесплатный HEX редактор (http://mh-nexus.de/en/hxd/), программа маленького размера, бинарный файл в несколько сотен килобайт.

Открыв в HxD ранее сохраненный в файл текст строки я увидел следующее:

<p>     </p>
3C 70 3E A0 20 A0 A0 A0 3C 2F 70 3E

Оказалось что между тегами присутствуют символ с кодом A0 (xA0), а также один символ пробела с кодом 20 (x20).

Посмотрев в таблицу с кодами символов стало понятно что это за символ с кодом xA0. Это тот же самый пробел только НЕРАЗРЫВНЫЙ:

Dec Hex Symbol HTML Number HTML name Description
160 A0   &#160; &nbsp; non-breaking space
32 20   &#32;   space

Дополнив шаблон регулярного выражения кодом данного символа, функция выполнила чистку как положено:

$txt=preg_replace( '#^<p>[xA0x20]+</p>#is', '' , $original_text );

Заключение

Не спеша, я потратил несколько часов времени чтобы разобраться с данным нюансом. Был получен интересный опыт и проблема решена! Вот такая вот магия ...

P.S. Работы проводились на PHP 5.3;

3 2223 PHP
Комментарии к публикации (3):
Вася #1Вася
15 Август 2018 17:52

Спасибо, друг! Помог! Помог сэкономить время!Very HappyVery Happy

+1
ph0en1x #2ph0en1x
15 Август 2018 19:11

Пожалуйста Wink. Рад что эта статья кому-то пригодилась!

0
Antonio #3Antonio
21 Ноябрь 2018 11:26

Столкнулся с аналогичной ситуацией в БД. Нашел, что вместо пробела стоит символ А0.  Полез искать что это за символ, и наткнулся на статью. Вот статья на Вики про неразрывный пробел: Неразрывный пробел

0