如何以最聪明的方式替换PHP中不同的换行符样式?

2022-08-30 12:08:06

我有一个文本,可能有不同的换行符样式。我想将所有换行符'\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 。

感谢您的帮助!


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

如果您不想替换所有 Unicode 换行符,而只想替换 CRLF 样式的换行符,请使用:

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

\R匹配这些换行符,是将输入字符串视为 UTF-8 的修饰符。u


来自 PCRE 文档

什么 \R 匹配

默认情况下,模式中的序列 \R 与任何 Unicode 换行符序列匹配,无论已选择为行结束序列。如果指定

     --enable-bsr-anycrlf

更改默认值,以便 \R 仅匹配 CR、LF 或 CRLF。在构建 PCRE 时选择的任何内容都可以在调用库函数时被覆盖。

换行符序列

在字符类之外,默认情况下,转义序列 \R 与任何 Unicode 换行符序列匹配。在非 UTF-8 模式下,\R 等效于以下内容:

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

这是一个“原子群”的例子,其细节如下。此特定组匹配后跟 LF 的双字符序列 CR,或单个字符 LF(换行符 U+000A)、VT(垂直制表符 U+000B)、FF(表单馈送,U+000C)、CR(回车符 U+000D)或 NEL(下一行 U+0085)之一。双字符序列被视为无法拆分的单个单元。

在 UTF-8 模式下,将添加两个码位大于 255 的附加字符:LS(行分隔符,U+2028)和 PS(段落分隔符,U+2029)。不需要 Unicode 字符属性支持即可识别这些字符。

通过在编译时或模式匹配时设置选项PCRE_BSR_ANYCRLF,可以将 \R 限制为仅匹配 CR、LF 或 CRLF(而不是完整的 Unicode 行尾集)。(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 () 和 Windows () 换行符替换为 Unix 等效项 ()。\r\r\n\n

我使用,因为它只需要一个字节而不是两个,但你可以很容易地把它改成.\n\r\n


推荐