Как заменить различные стили новой строки в 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.
Спасибо вам за вашу помощь!
4 answers
$string = preg_replace('~\R~u', "\r\n", $string);
Если вы не хотите заменять все новые строки Юникода, а только строки в стиле CRLF, используйте:
$string = preg_replace('~(*BSR_ANYCRLF)\R~', "\r\n", $string);
\R
соответствует этим новым строкам, u
является модификатором для обработки входной строки как UTF-8.
Из Документов PCRE:
Что
\R
соответствуетПо умолчанию последовательность \R в шаблоне соответствует любой новой строке Юникода последовательность, независимо от того, что было выбрано в качестве последовательности окончания строки. Если ты укажите
--enable-bsr-anycrlf
Значение по умолчанию изменено таким образом, что \R соответствует только CR, LF или CRLF. Все, что выбрано при создании PCRE, может быть переопределено, когда библиотека вызываются функции.
И
Последовательности новых строк
За пределами класса символов по умолчанию escape-последовательность \R совпадает любая последовательность новой строки в Юникоде. В режиме, отличном от 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 (вместо полного набора окончаний строк в Юникоде), установив опцию 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.
Для нормализации новых строк я всегда использую:
$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);
Это намного проще, чем регулярные выражения.