PHP preg_replace,包装以每个开头的行

时间:2017-08-10 13:45:22

标签: php regex preg-replace

我正在尝试用标签包装以“##”开头的每一行。尝试为文本格式化实现类似GitHub / Stackoverflow的语法。

这就是我得到的:

$value = preg_replace('/^## (.*)$/m', '<p>$1</p>', $value);

谷歌搜索了一段时间后,这似乎是正确的解决方案,但它没有按预期工作或我只是不明白的东西......

示例文字:

## Some header 1

Some text that doesn't need to be altered

## Some header 2

这就是结果:

<p>Some header 1
</p>

Some text that doesn't need to be altered

<p>Some header 2</p>

如您所见,第二个标题处理正常,因为它位于文本的末尾。但是,第一个标题在结束标记之前的末尾会得到一个额外的新行。我该如何摆脱它?

1 个答案:

答案 0 :(得分:2)

似乎在您当前的PCRE设置中,一个点匹配LF以外的所有字符(\n,换行符),因此它匹配CR(\r,回车),并且也是一个换行符。

PCRE支持覆盖默认换行符(以及$锚点的行为)。要使.匹配除CR和LF之外的所有字符,请启用相应的标志:

'/(*ANYCRLF)^## (.*)$/m'
  ^^^^^^^^^^

$将在\r\n之前断言行尾。

rexegg.com处详细了解此动词和其他动词:

  

默认情况下,当编译PCRE时,你会告诉它在遇到.时要考虑换行(除非在dotall mode中,否则它与换行符不匹配),以及multiline mode中的^$锚点行为。您可以使用以下修饰符覆盖此默认值:

     

(*CR)只有回车才被视为换行符   ✽(*LF)只有换行符被视为换行符(如在Unix上)   ✽(*CRLF)只有回车符后跟换行符才被视为换行符(如Windows)   ✽(*ANYCRLF)以上三种中的任何一种都被认为是换行符   ✽(*ANY)任何Unicode换行序列都被视为换行符

     

例如,(*CR)\w+.\w+匹配Line1\nLine2,因为该点可以匹配\n,这不被认为是换行符。见demo