Как заменить различные стили новой строки в PHP самым умным способом?

У меня есть текст, который может иметь разные стили новой строки. Я хочу заменить все новые строки '\ r\n', '\n', '\ r' той же новой строкой (в этом случае \r\n).

Какой самый быстрый способ сделать это? Мое текущее решение похоже на то, что является способом sucky:

    $sNicetext = str_replace("\r\n",'%%%%somthing%%%%', $sNicetext);
    $sNicetext = str_replace(array("\r","\n"),array("\r\n","\r\n"), $sNicetext);
    $sNicetext = str_replace('%%%%somthing%%%%',"\r\n", $sNicetext);

Проблема в том, что вы не можете сделать это с одной заменой, потому что \r\n будет дублироваться в \r\n\r\n.

Благодарим за помощь!

Ответ 1

$string = preg_replace('~\R~u', "\r\n", $string);

Если вы не хотите заменять все строки перевода Unicode, но только в стиле CRLF, используйте:

$string = preg_replace('~(*BSR_ANYCRLF)\R~', "\r\n", $string);

\R соответствует этим новым строкам, u является модификатором для обработки входной строки как UTF-8.


В документах PCRE:

Что \R соответствует

По умолчанию последовательность \R в шаблоне соответствует любой новой строке Unicode       последовательность, все, что было выбрано в качестве последовательности окончания строки. Если       вы указываете

     --enable-bsr-anycrlf

по умолчанию изменяется так, что \R соответствует только CR, LF или CRLF. Независимо от того, что выбрано при создании PCRE, можно переопределить, когда библиотека       функции вызываются.

и

Последовательности новой строки

Вне класса символов по умолчанию выполняется escape-последовательность\R        любая последовательность строк Unicode. В режиме не-UTF-8\R эквивалентно        следующее:

    (?>\r\n|\n|\x0b|\f|\r|\x85)

Это пример "атомной группы", подробности которой даны        ниже. Эта конкретная группа соответствует либо двухсимвольной последовательности        CR, за которым следует LF, или один из одиночных символов LF (linefeed,        U + 000A), VT (вертикальная вкладка, U + 000B), FF (formfeed, U + 000C), CR (каретка        return, U + 000D) или NEL (следующая строка, U + 0085). Двухсимвольная последовательность        рассматривается как единое целое, которое нельзя разделить.

В режиме UTF-8 два дополнительных символа, чьи кодовые точки больше        чем 255: LS (разделитель строк, U + 2028) и PS (разделитель абзацев, U + 2029). Поддержка свойств символа Unicode не требуется для        эти символы должны быть распознаны.

Можно ограничить \R, чтобы он соответствовал только CR, LF или CRLF (вместо        полный набор окончаний строки Unicode), установив опцию        PCRE_BSR_ANYCRLF либо во время компиляции, либо когда шаблон сопоставляется.        (BSR является сокращением для "обратной косой черты R".) Это можно сделать по умолчанию        когда создается PCRE; если это так, то другое поведение может быть        запрошенном через параметр PCRE_BSR_UNICODE. Также возможно        укажите эти настройки, запустив строку шаблона с одним из        следующие последовательности:

    (*BSR_ANYCRLF)   CR, LF, or CRLF only
    (*BSR_UNICODE)   any Unicode newline sequence

Они переопределяют значение по умолчанию и параметры, заданные для pcre_compile() или        pcre_compile2(), но они могут быть переопределены параметрами, предоставленными        pcre_exec() или pcre_dfa_exec(). Обратите внимание, что эти специальные настройки, которые        не являются Perl-совместимыми, признаются только в самом начале        и что они должны быть в верхнем регистре. Если более одного из них        присутствует, последний используется. Их можно комбинировать со сменой        соглашение о новой линии; например, шаблон может начинаться с:

    (*ANY)(*BSR_ANYCRLF)

Их также можно комбинировать с специальными последовательностями (* UTF8) или (* UCP).        Внутри класса символов \R рассматривается как непризнанный выход        последовательности и, таким образом, соответствует букве "R" по умолчанию, но вызывает ошибку        если установлен PCRE_EXTRA.

Ответ 2

Для нормализации новых строк я всегда использую:

$str = preg_replace('~\r\n?~', "\n", $str);

Он заменяет старые строки Mac (\r) и Windows (\r\n) эквивалентом Unix (\n).

Я предпочитаю использовать \n, потому что он принимает только один байт вместо двух, но вы можете легко изменить его на \r\n.

Ответ 3

Как насчет

$sNicetext = preg_replace('/\r\n|\r|\n/', "\r\n", $sNicetext);

Ответ 4

Я думаю, что самый умный/простой способ конвертировать в CRLF:

$output = str_replace("\n", "\r\n", str_replace("\r", '', $input));

для преобразования только в LF:

$output = str_replace("\r", '', $input);

это намного проще, чем регулярные выражения.