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

时间:2013-09-09 14:09:18

标签: php regex

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

以下是我目前的情况:

$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;处不是固定长度。我不知道如何解决这个问题。

有想法的人吗?

2 个答案:

答案 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

查看regex demo

此外,由于要动态构建模式,因此需要preg_quote $word和定界符(此处为/)。

您的解决方案是

$this->parsed = preg_replace(
    '/\[[^][]*\[[^][]*]](*SKIP)(*FAIL)|\b(?:' . preg_quote($word, '/') . ')\b/', 
    '[$0[' . implode(",", array_unique($types)) . ']]',
    $this->parsed);

\[[^][]*\[[^][]*]]正则表达式将匹配用替换模式包装的所有匹配项:

  • \[-一个[
  • [^][]*-除[]以外的0多个字符
  • \[-一个[字符
  • [^][]*-除[]以外的0多个字符
  • ]]-一个]]子字符串。