您好我的问题很简单:
我想在文章中匹配所有可能的主题标签,只要它们位于带有PCRE正则表达式的<figcaption>
中。 E.g:
<figcaption>blah blah #hashtag1, #hashtag2</figcaption>
我在此处https://regex101.com/r/aL9vS8/1进行了尝试,删除最后一个?
会将捕获从#hashtag1
更改为#hashtag2
,但无法同时获取这两者。
我甚至不确定它在PHP中的单个正则表达式中是否可行。
有什么想法可以帮助我吗? :)
如果一个正则表达式中没有办法(真的吗?甚至使用递归(?R)?
?:p),请建议最有效的表现方式。
谢谢!
[编辑]
如果没办法,我的PHP下一个想法就是:
preg_replace_callback
#hashtag
。我可以就此发表意见吗?有没有更好的办法?我的文章不长。
答案 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+序列:
(?:(?:<(?!\/figcaption>)|#\B)[^<#]*)*
- (?:<(?!\/figcaption>)|#\B)
未跟随<
或/figcaption>
未跟随字词char #
- 除[^<#]*
和<
#
- 省略目前为止匹配的文字\K
- #\w+
和1 + word chars 更多细节:
\K
:转义序列
#
导致任何先前匹配的字符不包含在最终匹配的序列中。例如,模式:\K
匹配
foo\Kbar
,但报告已匹配foobar
。此功能类似于lookbehind断言。
bar
:在这里,我们有一个外部非捕获组(?:(?:<(?!\/figcaption>)|#\B)[^<#]*)*
,可以将子模式序列匹配零次或多次(我们只能将量词(?:...)*
设置为分组如果我们需要重复子模式的序列,那么内部非捕获组*
只是缩小更长(?:<(?!\/figcaption>)|#\B)[^<#]*
的一种方法(只是对2组不同的替代{在公共“后缀”<(?!\/figcaption>)[^<#]*|#\B[^<#]*
之前{1}}和<(?!\/figcaption>)
。#\B
替换模式{/ 1}}:代码:
[^<#]*