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

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

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

    $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 .

Спасибо за помощь!

5 ответов

Решение
$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 (перевод строки, U+000A), VT (вертикальная табуляция, U+000B), FF (подача формы, U+000C), CR (возврат каретки, U+000D) или NEL (следующая строка, U+0085). Двухсимвольная последовательность рассматривается как единое целое, которое не может быть разделено.

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

Можно ограничить \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 обрабатывается как нераспознанная escape-последовательность и поэтому по умолчанию соответствует букве "R", но вызывает ошибку, если установлен PCRE_EXTRA.

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

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

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

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

Как насчет

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

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

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

конвертировать только в LF:

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

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

      $sNicetext = str_replace(["\r\n", "\r"], "\n", $sNicetext);

также работает

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