Помогите с регулярным выражением, которое удаляет ведущие пробелы
Вопрос
Я изменяю основную функцию библиотеки Kohana, текст::auto_p() функция.
Функция описывает себя как «nl2br() на стероидах».По сути, это обеспечивает <br />
одинарные разрывы строк, но двойные разрывы строк окружены символом <p>
теги.
Ограничение, которое я обнаружил, заключается в том, что оно будет, но <br />
это в <pre>
элемент.Это создаст двойные новые строки, а это не то, чего я хочу.Я внес модификацию, позволяющую получать pre-элементы с помощью регулярного выражения и обратного вызова, который удаляет <br />
который работает нормально.
Однако основная проблема заключается в том, что в моем тексте есть примеры кода, которые получают auto_p()
'd, и мне нужно сохранить отступы (для удобства чтения).К сожалению для меня, функция удаляет начальные и конечные пробелы в строках.
Вот регулярное выражение, которое удаляет ведущий пробел
$str = preg_replace('~^[ \t]+~m', '', $str);
Я не лучший гуру регулярных выражений, но я почти уверен, что там написано: «Получите ведущие пробелы и табуляции там, где есть хотя бы один, и замените их пустой строкой».
Я пробовал удалить эту строку, но потом она добавит <br />
где они мне определенно не нужны - в одном случае я получал такой результат
<ul><br />
<li>something</li>
</ul>
Как мне изменить это регулярное выражение или код, чтобы не удалять ведущее пространство внутри <pre>
элемент?
Оригинальная вспомогательная функция от Kohana доступна здесь..(пролистнуть почти вниз).
Я знаю, что получу несколько ответов типа «Использовать парсер HTML» - и хотя вы, возможно, правы, существующий код просто использует регулярное выражение, и я бы предпочел более простое решение (где мне не нужно включать библиотеку и т.д.) .
Спасибо за ваше время.
Решение
Вот как бы я это сделал:
$str = preg_replace(
'~^[ \t]++(?=(?:[^<]++|<(?!/?+pre\b))*+(?:\z|<pre\b))~im',
'', $str);
После сопоставления некоторых пробелов в начале строки, упреждающий просмотр просматривает вперед <pre>
или </pre>
теги.Суть предпросмотра заключается в следующем:
(?:[^<]++|<(?!/?+pre\b))*+
Он соответствует нулю или более чему-либо, кроме левой угловой скобки, или левая угловая скобка, если это не начало <pre>
или </pre>
ярлык.Эта часть перестанет соответствовать только тогда, когда встретит <pre>
(начальный) тег, a </pre>
(конечный) тег или конец ввода.Если это закрывающий тег, который останавливает его, вы знаете, что находитесь внутри <PRE>
элемент, поэтому вы не хотите выполнять замену.
Притяжательные кванторы ('++'
, '*+'
, и '?+'
) необходимы для предотвращения катастрофический возврат назад.(Я не могу с этим поделать:эта фраза всегда заставляет меня думать о сценарий резонансного каскада от Период полураспада.)
Этот метод также предполагает достаточно правильно сформированный HTML, т. е. все <pre>...</pre>
теги правильно сбалансированы.Теги внутри комментариев SGML тоже все испортят, если только они не сбалансированы.Вы также можете справиться с комментариями, если не против сделать регулярное выражение в два раза длиннее и в три раза уродливее.:)
Другие советы
Думаю, ваша проблема много обсуждается - перейдите по этой ссылке.
http://us3.php.net/manual/en/function.nl2br.php#91828
Этот тоже: