仅在单个正则表达式

时间:2016-07-20 07:32:03

标签: php regex

您好我的问题很简单:

我想在文章中匹配所有可能的主题标签,只要它们位于带有PCRE正则表达式的<figcaption>中。 E.g:

<figcaption>blah blah #hashtag1, #hashtag2</figcaption>

我在此处https://regex101.com/r/aL9vS8/1进行了尝试,删除最后一个?会将捕获从#hashtag1更改为#hashtag2,但无法同时获取这两者。

我甚至不确定它在PHP中的单个正则表达式中是否可行

有什么想法可以帮助我吗? :)

如果一个正则表达式中没有办法(真的吗?甚至使用递归(?R)??:p),请建议最有效的表现方式。

谢谢!

[编辑]

如果没办法,我的PHP下一个想法就是:

  1. 将每个figcaption与preg_replace_callback
  2. 匹配
  3. 在回调中匹配#hashtag
  4. 的每个实例

    我可以就此发表意见吗?有没有更好的办法?我的文章不长。

1 个答案:

答案 0 :(得分:2)

  

请建议最有效的表现方式

在某些分隔符与PCRE正则表达式之间匹配某些文本的最可靠方法是使用\G operator的自定义边界。但是,尾随边界是一个多字符串,除了</figcaption>之外的任何文本都需要tempered greedy token。由于此令牌非常耗费资源,因此必须将其展开。

这是一个快速,可靠的PCRE正则表达式,适用于您的任务:

(?:<figcaption|(?!^)\G)[^<#]*(?:(?:<(?!\/figcaption>)|#\B)[^<#]*)*\K#\w+

请参阅regex demo

<强>详情:

  • (?:<figcaption|(?!^)\G) - 匹配<figcaption或上一次成功匹配的结束
    更多详细信息:
    (?:<figcaption|(?!^)\G)非捕获组(?:...))这意味着只对组进行分组,而不是跟踪与该组匹配的内容(即,未创建堆栈时没有保留任何值,因为没有创建堆栈)匹配2个备选项(|是一个交替运算符): 1)文字文本<figcaption或2)(?!^)\G - 上一次成功匹配后的位置(注意\G也匹配字符串的开头,因此,我们必须添加否定前瞻{ {1}}排除该行为。)。
  • (?!^) - 除[^<#]*<
  • 以外的0个字符
  • # - 0+序列:
    • (?:(?:<(?!\/figcaption>)|#\B)[^<#]*)* - (?:<(?!\/figcaption>)|#\B)未跟随</figcaption>未跟随字词char
    • # - 除[^<#]*<
    • 以外的0个字符
  • # - 省略目前为止匹配的文字
  • \K - #\w+和1 + word chars

更多细节

  

转义序列#导致任何先前匹配的字符不包含在最终匹配的序列中。例如,模式:

\K
     

匹配foo\Kbar ,但报告已匹配foobar。此功能类似于lookbehind断言。

  • bar:在这里,我们有一个外部非捕获组(?:(?:<(?!\/figcaption>)|#\B)[^<#]*)*,可以将子模式序列匹配零次或多次(我们只能将量词(?:...)*设置为分组如果我们需要重复子模式的序列,那么内部非捕获组*只是缩小更长(?:<(?!\/figcaption>)|#\B)[^<#]*的一种方法(只是对2组不同的替代{在公共“后缀”<(?!\/figcaption>)[^<#]*|#\B[^<#]*之前{1}}和<(?!\/figcaption>)
  • 包装标签:只需使用#\B替换模式{/ 1}}:

代码:

[^<#]*

请参阅PHP IDEONE demo