【问题标题】:Matching end of line position using m flag with different line ending styles使用具有不同行尾样式的 m 标志匹配行尾位置
【发布时间】:2017-08-10 13:45:22
【问题描述】:

我正在尝试用标签包装以“##”开头的每一行。尝试实现类似于 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>

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

【问题讨论】:

  • github使用的语法是MarkDown。我建议你使用像github.com/erusev/parsedown 这样的现有库来解析你的文本
  • 在您的代码中没有发现任何问题,请查看3v4l.org/I8ICB
  • 这很有趣。试试'/(*ANYCRLF)^## (.*)$/m'
  • 它确实有效,Wiktor,谢谢!你应该让它成为一个答案。我发现它实际上是在该字符串的末尾添加一个“\r”,而不是一个“\n”。如果有什么不同,我正在 Laravel 工作。这个 (*ANYCRLF) 部分是什么意思?
  • 我可以看到在线代码运行良好,Chetan,这很奇怪。

标签: php regex preg-replace


【解决方案1】:

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

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

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

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

rexegg.com查看更多关于这个和其他动词的信息:

默认情况下,当 PCRE 被编译时,你告诉它在遇到 . 时认为什么是换行符(因为它不匹配换行符,除非在 dotall mode 中),以及 @ 987654333@ 和 $ 锚点在 multiline mode 中的行为。您可以使用以下修饰符覆盖此默认值:

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

例如,(*CR)\w+.\w+ 匹配 Line1\nLine2,因为点能够匹配 \n,这不被视为换行符。见demo

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-25
    • 1970-01-01
    • 2018-10-24
    • 1970-01-01
    • 2013-06-22
    相关资源
    最近更新 更多