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

Car*_*itz 35 php replace newline unify

我有一个可能有不同换行样式的文本.我想用相同的换行符替换所有换行符'\ 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);
Run Code Online (Sandbox Code Playgroud)

问题是您无法通过一次替换来执行此操作,因为\ r \n将复制到\ r \n\r \n.

谢谢您的帮助!

Nik*_*kiC 87

$string = preg_replace('~\R~u', "\r\n", $string);
Run Code Online (Sandbox Code Playgroud)

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

$string = preg_replace('~(*BSR_ANYCRLF)\R~', "\r\n", $string);
Run Code Online (Sandbox Code Playgroud)

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


来自PCRE文档:

什么\R匹配

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

     --enable-bsr-anycrlf
Run Code Online (Sandbox Code Playgroud)

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

换行序列

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

    (?>\r\n|\n|\x0b|\f|\r|\x85)
Run Code Online (Sandbox Code Playgroud)

这是"原子组"的一个例子,其细节在下面给出.此特定组匹配双字符序列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).要识别这些字符,不需要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
Run Code Online (Sandbox Code Playgroud)

这些覆盖了pcre_compile()或pcre_compile2()的默认值和选项,但是它们可以被赋予pcre_exec()或pcre_dfa_exec()的选项覆盖.请注意,这些不与Perl兼容的特殊设置仅在模式的最开头才能识别,并且必须为大写.如果存在多个,则使用最后一个.它们可以与换行符约定相结合; 例如,模式可以从以下开始:

    (*ANY)(*BSR_ANYCRLF)
Run Code Online (Sandbox Code Playgroud)

它们还可以与(*UTF8)或(*UCP)特殊序列组合使用.在字符类中,\ R被视为无法识别的转义序列,因此默认情况下匹配字母"R",但如果设置了PCRE_EXTRA则会导致错误.

  • 您还可以使用PHP_EOL来匹配文件的安装结束.preg_replace('〜\ R~u',PHP_EOL,$ string); (3认同)

Ali*_*xel 15

为了规范换行,我总是使用:

$str = preg_replace('~\r\n?~', "\n", $str);
Run Code Online (Sandbox Code Playgroud)

它用Unix等价物()替换旧的Mac(\r)和Windows(\r\n)换行符\n.

我喜欢使用,\n因为它只需要一个字节而不是两个字节,但您可以轻松地将其更改为\r\n.


Tom*_*lak 9

怎么样

$sNicetext = preg_replace('/\r\n|\r|\n/', "\r\n", $sNicetext);
Run Code Online (Sandbox Code Playgroud)

  • 第二个字符串需要双引号;) (6认同)
  • 哇.这......*你*就把它放在那里!;)老实说,我完全惊讶.我非常确定变量插值是唯一的区别,我甚至都不打算查找它.好的谢谢.学到了一些东西.:-) - 并修复了我的代码示例. (4认同)
  • 因为转义序列仅在双引号中解析。正则表达式没问题,因为它会额外解析转义序列,但不适用于所有其他字符串。因此第二个参数需要双引号,否则你将输出普通的 \r\n,而不是换行符 (2认同)
  • @Tomalek http://codepad.viper-7.com/XJpmkP(因为你不相信我,看看文档:http://www.php.net/manual/en/language.types. string.php) (2认同)

Roe*_*oey 5

我认为转换为 CRLF 的最聪明/最简单的方法是:

$output = str_replace("\n", "\r\n", str_replace("\r", '', $input));
Run Code Online (Sandbox Code Playgroud)

仅转换为 LF:

$output = str_replace("\r", '', $input);
Run Code Online (Sandbox Code Playgroud)

它比正则表达式容易得多。