【问题标题】:Regex to match (1 or more) php heredocs containing an empty line正则表达式匹配(1 个或多个)包含空行的 php heredocs
【发布时间】:2019-08-31 17:20:47
【问题描述】:

示例文本位于:https://regex101.com/r/tfYEkO/1

我想在 php 代码中找到包含空行的 heredocs。

我可以使用这个正则表达式来做到这一点,但如果一个文件中有 2 个 heredocs,它会从第一个的开头匹配到第二个的结尾:

<<<([A-Z]+)\n.*\n\n.*\n *\1\b

所以我认为负前瞻可以解决它,但这与任何事情都不匹配:

<<<([A-Z]+)\n(?!.*\1.*).*\n\n(?!.*\1.*).*\n *\1\b

我不认为我可以使用带有.* 的负面回溯。我尝试了不贪婪的标志,但这似乎并没有改变它。

仅供参考,php中的heredoc以&lt;&lt;&lt;和一个关键字开头,并以该关键字在它自己的行结束:

$foo = <<<HTML
This is the string that is returned.

It can contain multiple lines.
HTML;

【问题讨论】:

  • 试试'~&lt;&lt;&lt;([A-Z]+)(?:\R(?!\s*\1;$).*)*\R(?:\R(?!\s*\1;$).*)*\R\s*\1;$~m',见demo。实际上,$ 可以替换为\R,因为NAME; 后面必须有一个换行符。

标签: php regex pcre regex-negation heredoc


【解决方案1】:

你可以使用

'~<<<([A-Za-z_]\w*)(?:\R(?!\1;\R).*)*\R(?:\R(?!\1;\R).*)*\R\1;\R~'

regex demo

要使其与 PHP 7.3 more lax requirements 兼容(现在可以缩进结束标记并移除结束标记后的新行要求),请使用

'~<<<([A-Za-z_]\w*)(?:\R(?!\h*\1;$).*)*\R(?:\R(?!\h*\1;$).*)*\R\h*\1;$~m'

查看另一个regex demo

详情

  • &lt;&lt;&lt; - 文字 &lt;&lt;&lt; 子字符串
  • ([A-Za-z_]\w*) - 第 1 组:有效的 PHP 标签(必须只包含字母数字字符和下划线,并且必须以非数字字符或下划线开头
  • (?:\R(?!\1;\R).*)* - 0 次或多次重复换行符 (\R) 后跟第 1 组中的值不同,后跟 ; 和换行符,然后是整行 (.*)
  • \R - 换行
  • (?:\R(?!\1;\R).*)* - 见上文(请注意,在 (?!\h*\1;$) 的情况下,它的意思是“后面没有 0+ 个水平空格、第 1 组值和 ; 在行尾”
  • \R - 换行
  • \1 - 与第 1 组中的值相同
  • ; - 分号
  • \R - 换行符/$ - 行尾(带有m 修饰符,$ 匹配行尾,而不是字符串尾)。

【讨论】:

  • 谢谢!出于我的目的,我更改为:&lt;&lt;&lt;([A-Z]{2,})(?:\n(?!\s*\1.*\n).*)*\n(?:\n(?!\s*\1.*\n).*)*\n\s*\1.*\n - 更改为更熟悉的\n,输入您建议的\s,并使用.* 而不是;,因为php v7.3 使heredoc 语法更加灵活.
  • @Redzarf 请注意,\R 匹配任何换行符,而不仅仅是\n,因此更安全。我建议使用'~&lt;&lt;&lt;([A-Za-z_]\w*)(?:\R(?!\h*\1;$).*)*\R(?:\R(?!\h*\1;$).*)*\R\h*\1;$~m',我在答案中添加了这个解决方案。
猜你喜欢
  • 1970-01-01
  • 2017-08-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-06-10
相关资源
最近更新 更多