正则表达式在未括在括号中时替换单词


Regex replace word when not enclosed in brackets

我正在尝试创建一个正则表达式,其中它替换未用括号括起来的单词。

这是我目前拥有的:

$this->parsed = preg_replace('/'b(?<!'[)('.preg_quote($word).')'b/','[$1['.implode(",",array_unique($types)).']]',$this->parsed);

其中$word可以是以下之一,"Burkely Mayfair Trunk"或"Trunk"。

它将取代这句话

这个伯克利梅菲尔树干相当不错

这个[伯克利梅菲尔[行李箱[产品名称]][产品名称]]很漂亮 好

虽然它应该成为

这个[伯克利梅菲尔树干[产品名称]]相当不错

由于它按最大字符串到最小字符串的顺序进行替换,因此不应在字符串的已替换部分中替换较小的字符串和/或单词部分的双重出现。当它是字符串的第一部分时,它起作用。

当我尝试进行动态后看时,它给出以下错误:"编译失败:回溯断言在偏移量 11 处不是固定长度"。我不知道如何解决这个问题。

有人有什么想法吗?

在又一个早上玩正则表达式之后,我想出了一个非常肮脏的解决方案,它根本不灵活,但适用于我的用例。

$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 个单词,并结合指定的关键字。

不过,很高兴听到是否有人有更好的解决方案。

您可以将

括号内的任何子字符串与'[[^][]*]模式匹配,然后使用 PCRE 动词(*SKIP)(*FAIL)删除匹配项,并且仅在任何其他上下文中匹配您的模式:

'[[^][]*](*SKIP)(*FAIL)|your_pattern_here

请参阅正则表达式演示。要跳过成对嵌套方括号内的匹配项,请使用带有子例程的基于回避的正则表达式(请注意,它必须使用捕获组):

(?<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+字符
  • ]] - ]]子字符串。