替换所有匹配,除非被包围或仅被包围

时间:2015-05-19 19:03:52

标签: php regex preg-replace

给定文本字符串(降价文档),我需要实现以下两个选项之一:

  • 在文档 EXCEPT 中替换特定表达式(ProductStateWorker)的所有匹配项,这些匹配项位于markdown图像语法(\W)(theWord)(\W)内。< / p>

  • 替换降价图像中特定表达式(![Blah theWord blah](url) ONLY 的所有匹配项,即:{{([^}}]+)}}\[\[[^\]\]]+\]\]

这两个表达式目前都匹配所有内容,无论是否在降价图像语法内部,我已经尝试过所有我能想到的内容。

Here is an example of the first option

And here is an example of the second option

任何帮助和/或线索都将受到高度赞赏。

提前致谢!

3 个答案:

答案 0 :(得分:2)

我修改了第一个表达式,因为我认为有一些额外的捕获组然后通过添加 lookahead 技巧来制作它们:

- 第一个(Live demo):

\b(vitae)\b(?![^[]*]\s*\()

- 第二个(Live demo):

{{([^}}]+)}}\[\[[^\]\]]+\]\](?=[^[]*]\s*\()

前瞻部分解释

(?!            # Starting a negative lookahead
    [^[]*]     # Everything that's between brackets
    \s*        # Any whitespace
    \(         # Check if it's followed by an opening parentheses  
)              # End of lookahead which confirms the whole expression doesn't match between brackets

(?=意味着积极向前看

答案 1 :(得分:1)

您可以利用丢弃技术,它对这种情况非常有用。它由以下模式组成:

patternToSkip1 (*SKIP)(*FAIL)|patternToSkip2 (*SKIP)(*FAIL)| MATCH THIS PATTERN

所以,根据你的需要:

  

在文档中替换特定表达式((\ W)(theWord)(\ W))的所有匹配项除了markdown图像语法中的匹配项

您可以在pcre(*SKIP)(*FAIL)标记中轻松实现此目的,因此对于您的情况,您可以使用这样的正则表达式:

\[.*?\](*SKIP)(*FAIL)|\bTheWord\b

或使用您的模式:

\[.*?\](*SKIP)(*FAIL)|(\W)(theWord)(\W)

这个正则表达式背后的想法是告诉正则表达式引擎跳过[中的内容...... ]

<强> Working demo

答案 2 :(得分:0)

第一个正则表达式很容易用SKIP-FAIL trick修复:

\!\[.*?\]\(http[^)]*\)(*SKIP)(*FAIL)|\bvitae\b

替换为您选择的单词。在PHP(PCRE)正则表达式中,它是一种完全有效的方法,可以匹配外部某些标记。

请参阅Demo 1

至于第二个,它更难,但是\G可以确保我们连续匹配内部一些标记:

(\!\[.*?|(?<!^)\G)((?>(?!\]\(http).)*?){{([^}]+?)}}\[{2}[^]]+?\]{2}(?=.*?\]\(http[^)]*?\))

替换为$1$2{{NEW_REPLACED_TEXT}}[[NEW_DIGITS]]

请参阅Demo 2

PHP:

$re1 = "#\!\[.*?\]\(http[^)]*\)(*SKIP)(*FAIL)|\bvitae\b#i";
$re2 = "#(\!\[.*?|(?<!^)\G)((?>(?!\]\(http).)*?){{([^}]+?)}}\[{2}[^]]+?\]{2}(?=.*?\]\(http[^)]*?\))#i";