Как удалить пустые строки из текста в PHP? - PullRequest
31 голосов
/ 02 апреля 2009

Мне нужно удалить пустые строки (с пробелами или абсолютно пустыми) в PHP. Я использую это регулярное выражение, но оно не работает:

$str = ereg_replace('^[ \t]*$\r?\n', '', $str);
$str = preg_replace('^[ \t]*$\r?\n', '', $str);

Я хочу получить результат:

blahblah

blahblah

   adsa 


sad asdasd

будет:

blahblah
blahblah
   adsa 
sad asdasd

Ответы [ 10 ]

72 голосов
/ 02 апреля 2009
// New line is required to split non-blank lines
preg_replace("/(^[\r\n]*|[\r\n]+)[\s\t]*[\r\n]+/", "\n", $string);

Вышеупомянутое регулярное выражение говорит:

/(^[\r\n]*|[\r\n]+)[\s\t]*[\r\n]+/
    1st Capturing group (^[\r\n]*|[\r\n]+)
        1st Alternative: ^[\r\n]*
        ^ assert position at start of the string
            [\r\n]* match a single character present in the list below
                Quantifier: Between zero and unlimited times, as many times as possible, giving back as needed [greedy]
                \r matches a carriage return (ASCII 13)
                \n matches a fine-feed (newline) character (ASCII 10)
        2nd Alternative: [\r\n]+
            [\r\n]+ match a single character present in the list below
            Quantifier: Between one and unlimited times, as many times as possible, giving back as needed [greedy]
            \r matches a carriage return (ASCII 13)
            \n matches a fine-feed (newline) character (ASCII 10)
    [\s\t]* match a single character present in the list below
        Quantifier: Between zero and unlimited times, as many times as possible, giving back as needed [greedy]
        \s match any white space character [\r\n\t\f ]
        \tTab (ASCII 9)
    [\r\n]+ match a single character present in the list below
        Quantifier: Between one and unlimited times, as many times as possible, giving back as needed [greedy]
        \r matches a carriage return (ASCII 13)
        \n matches a fine-feed (newline) character (ASCII 10)
25 голосов
/ 02 апреля 2009

Ваше решение ereg-replace() неверно, поскольку методы ereg/eregi устарели. Ваш preg_replace() даже не будет компилироваться, но если вы добавите разделители и установите многострочный режим, он будет работать нормально:

$str = preg_replace('/^[ \t]*[\r\n]+/m', '', $str);

Модификатор m позволяет ^ соответствовать началу логической строки, а не только началу всей строки. Якорь начала строки необходим, потому что без него регулярное выражение будет соответствовать новой строке в конце каждой строки, а не только пустым. Вам не нужен якорь в конце строки ($), потому что вы активно сопоставляете символы новой строки, но это не повредит.

Принятый ответ выполняет работу, но это сложнее, чем нужно. Регулярное выражение должно соответствовать либо началу строки (^[\r\n]*, многострочный режим не задан), либо хотя бы одной новой строке ([\r\n]+), за которой следует хотя бы одна новая строка ([\r\n]+). Таким образом, в особом случае строки, которая начинается с одной или нескольких пустых строк, они будут заменены на одну пустую строку. Я уверен, что это не желаемый результат.

Но большую часть времени он выполняет замену двух или более последовательных символов новой строки вместе с любым горизонтальным пробелом (пробелами или табуляцией), который находится между ними, с одним переводом строки. В любом случае, это намерение. Автор, похоже, ожидает, что \s будет соответствовать только пробелу (\x20), хотя на самом деле он соответствует любому пробелу. Это очень распространенная ошибка. Фактический список варьируется от одного варианта регулярного выражения к следующему, но как минимум вы можете ожидать, что \s будет соответствовать любому [ \t\f\r\n] совпадению.

На самом деле, в PHP у вас есть лучший вариант:

$str = preg_replace('/^\h*\v+/m', '', $str);

\h соответствует любому горизонтальному пробелу, а \v соответствует вертикальному пробелу.

10 голосов
/ 23 октября 2015

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

$tmp = explode("\n", $str);
$tmp = array_filter($tmp);
$str = implode("\n", $tmp);

или в одну строку:

$str = implode("\n", array_filter(explode("\n", $str)));

Не знаю, но, возможно, это быстрее, чем preg_replace.

6 голосов
/ 03 марта 2012

Комментарий от Bythos по ссылке Джейми выше работал для меня:

/^\n+|^[\t\s]*\n+/m

Я не хотел убирать все новые строки, только пустые / пробельные. Это делает трюк!

1 голос
/ 03 июня 2018

Нет необходимости слишком усложнять вещи, это можно сделать с помощью простого короткого регулярного выражения:

$text = preg_replace("/(\R){2,}/", "$1", $text);

(\R) соответствует всем новым строкам
{2,} соответствует двум или более вхождениям
$1 Использует первую обратную ссылку (EOL для конкретной платформы) в качестве замены

1 голос
/ 08 ноября 2013

Попробуйте это:

$str =preg_replace("/(^[\r\n]*|[\r\n]+)[\s\t]*[\r\n]+/", "\r\n", $str);

Если вы выводите это в текстовый файл, он выдаст тот же вывод на простом блокноте, Wordpad, а также на текстовых редакторах, например Notepad ++.

1 голос
/ 02 апреля 2009

что по этому поводу?

$str = preg_replace('^\s+\r?\n$', '', $str);
0 голосов
/ 19 апреля 2017

С этот ответ , у меня нормально работает

$str = "<html>
<body>";

echo str_replace(array("\r", "\n"), '', $str);
0 голосов
/ 16 января 2015

Принятый ответ оставляет дополнительный разрыв строки в конце строки. Использование rtrim() удалит этот окончательный перевод строки:

rtrim(preg_replace("/(^[\r\n]*|[\r\n]+)[\s\t]*[\r\n]+/", "\n", $string));
0 голосов
/ 04 октября 2011
function trimblanklines($str) {
    return preg_replace('`\A[ \t]*\r?\n|\r?\n[ \t]*\Z`','',$str);
}

Этот удаляет только их начало и конец, а не середину (если кто-то еще искал это).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...