2016-07-20 39 views
2

大家好,我的问题很简单的一组:比赛多次只在单一的正则表达式

我想匹配,只有当他们在与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. 在回调比赛#hashtag每个实例。

我可以就此了解你的意见吗?有没有更好的办法?我的文章不是很长。

+0

figcaption是一个HTML标签。您可以使用JS来获得figcaption文本,然后开始寻找使用正则表达式的井号标签的搜索。 – rmondesilva

+1

的可能的复制(HTTP [如何捕获在JavaScript正则表达式组的任意号码?]://计算器。com/questions/3537878/how-to-capture-an-arbitrary-number-of-groups-in-javascript-regexp) –

+0

这里的要点是没有必要匹配“任意数量的组”,这个问题是不是上述的一个骗局。实际上,JS标签应该被删除,共享的尝试是一个PCRE正则表达式。 –

回答

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也匹配字符串的开始,因此,我们必须添加负先行(?!^)排除行为)。
  • [^<#]* - 比<其他0+字符和#
  • (?:(?:<(?!\/figcaption>)|#\B)[^<#]*)* - 的0+序列:
    • (?:<(?!\/figcaption>)|#\B) - 一个<后面没有与/figcaption>#或没有遵循与字炭
    • [^<#]* - 0 +字符除<#
  • \K - 忽略文本到目前为止匹配
  • #\w+ - #和1+字字符

更细节

逃逸序列\K导致任何公关明显匹配的字符不包含在最终的匹配序列中。例如,模式:

foo\Kbar 

比赛foobar,但报告说,它匹配了bar。该功能类似于后向断言。

  • (?:(?:<(?!\/figcaption>)|#\B)[^<#]*)*:在这里,我们有一个外非捕获组(?:...)*使匹配子模式零次或多次的序列(能量词*设置为仅一个分组,如果我们需要重复一个序列的子模式)与内非捕获组(?:<(?!\/figcaption>)|#\B)[^<#]*只是一个收缩方式较长<(?!\/figcaption>)[^<#]*|#\B[^<#]*(只是第2层不同的替代<(?!\/figcaption>)#\B一个共同的“后缀” [^<#]*之前
  • 包装在一个标签:只使用preg_replace<span class="highlight">$0</span>替换模式:

代码:

$re = '~(?:<figcaption|(?!^)\G)[^<#]*(?:(?:<(?!\/figcaption>)|#\B)[^<#]*)*\K#\w+~'; 
$str = "<figcaption>blah # blah #hashtag1, #hashtag2</figcaption> #ee <figcaption>#ddddd"; 
$subst = "<span class=\"highlight\">$0</span>"; 
$result = preg_replace($re, $subst, $str); 
echo $result; 

PHP IDEONE demo

+0

Waw非常感谢!这听起来很棒,工作...你能帮我更好地了解你的正则表达式一步一步来帮助我捕获后来更换的hashtag? – antoni

+0

你不需要*捕获*标签,它是*匹配*这种方式。即使标签被破坏,在打开“

+0

试着对你的例子进行尝试,我可以做出我想要的替换。完善!真棒!只是希望你可以将你的模式分解成更多的解释,需要一段时间才能理解haha – antoni