我试图创建一个正则表达式,用它替换未用括号括起来的单词。
以下是我目前的情况:
$this->parsed = preg_replace('/\b(?<!\[)('.preg_quote($word).')\b/','[$1['.implode(",",array_unique($types)).']]',$this->parsed);
$ word可以是以下之一,&#34; Burkely Mayfair Trunk&#34;或&#34; Trunk&#34;。
它将取代句子
这个Burkely Mayfair Trunk很不错
的
这[Burkely Mayfair [主干[产品名称]] [产品名称]很漂亮 好的
虽然它应该成为
这[Burkely Mayfair Trunk [productname]]非常好
由于它按照最大字符串的顺序替换为最小字符串,因此字符串的较小字符串和/或双重出现不应替换为字符串的已替换部分。当它是字符串的第一部分时,它就可以工作。
当我尝试进行动态的lookbehind时,会出现以下错误:&#34;编译失败:lookbehind断言在偏移量11和#34;处不是固定长度。我不知道如何解决这个问题。
有想法的人吗?
答案 0 :(得分:0)
在玩了正则表达式的另一个早晨之后,我提出了一个非常肮脏的解决方案,它根本不灵活,但适用于我的用例。
$this->parsed = preg_replace('/\b(?!\[(|((\w+)(\s|\.))|((\w+)(\s|\.)(\w+)(\s|\.))))('.preg_quote($word).')(?!(((\s|\.)(\w+))|((\s|\.)(\w+)(\s|\.)(\w+))|)\[)\b/s','[$10['.implode(",",array_unique($types)).']]',$this->parsed);
它基本上做的是检查括号中没有单词,前面或后面的1个单词或2个单词以及指定的关键字。
但是,如果有人有更好的解决方案,那将会很棒。
答案 1 :(得分:0)
您可以使用\[[^][]*]
模式匹配括号内的任何子字符串,然后使用(*SKIP)(*FAIL)
PCRE verbs删除匹配项,并且仅在任何其他上下文中匹配您的模式:
\[[^][]*](*SKIP)(*FAIL)|your_pattern_here
请参见regex demo。要跳过成对的嵌套方括号内的匹配,请使用带有子例程的基于重新配置的正则表达式(注意,它必须使用捕获组):
(?<skip>\[(?:[^][]++|(?&skip))*])(*SKIP)(*FAIL)|your_pattern_here
此外,由于要动态构建模式,因此需要preg_quote
$word
和定界符(此处为/
)。
您的解决方案是
$this->parsed = preg_replace(
'/\[[^][]*\[[^][]*]](*SKIP)(*FAIL)|\b(?:' . preg_quote($word, '/') . ')\b/',
'[$0[' . implode(",", array_unique($types)) . ']]',
$this->parsed);
\[[^][]*\[[^][]*]]
正则表达式将匹配用替换模式包装的所有匹配项:
\[
-一个[
[^][]*
-除[
和]
以外的0多个字符\[
-一个[
字符[^][]*
-除[
和]
以外的0多个字符]]
-一个]]
子字符串。