3

有限的正则表达式经验,我正在使用 preg_replace 使用 PHP。

我想替换不在 [no-glossary] ... [/no-glossary] 标签之间的指定“单词”。如果它们不是“单词”和标签之间的空格,或者如果它们是“单词”之后的空格,我的表达就有效,但是如果我在单词之前放置一个空格(预期)它会失败!

这些工作:

$html = '<p>Do not replace [no-glossary]this[/no-glossary] replace this.</p>';
$html = '<p>Do not replace [no-glossary]this [/no-glossary] replace this.</p>';

这不会:

$html = '<p>Do not replace [no-glossary] this [/no-glossary] replace this.</p>';

使用的模式逐部分解释

/                      - find
(?<!\[no-glossary\])   - Not after the [no-glossary] tag
[ ]*                   - Followed by 0 or more spaces (I think this is the problem)
\b(this)\b             - The word "this" between word boundaries
[ ]*                   - Followed by 0 or more spaces
(?!\[\/no-glossary\])  - Not before the [/no-glossary] tag
/

这是代码:

$pattern = "/(?<!\[no-glossary\])[ ]*\b(this)\b[ ]*(?!\[\/no-glossary\])/"; 
$html = '<p>Do not replace [no-glossary] this [/no-glossary] replace this.</p>';
$html = preg_replace($pattern, "that", $html);

print $html;

输出:

<p>Do not change [no-glossary] that [/no-glossary] changethat.</p>

问题:

  1. 标签之间的单词已更改。
  2. 在正确替换的第二个单词前面删除了空格。
4

5 回答 5

3

只需捕获空格:

$subject = <<<LOD
<p>Do not replace [no-glossary]this[/no-glossary] replace this.</p>
<p>Do not replace [no-glossary]this [/no-glossary] replace this.</p>
<p>Do not replace [no-glossary] this[/no-glossary] replace this.</p>
<p>Do not replace [no-glossary] this [/no-glossary] replace this.</p>
LOD;
$pattern = '`(?<!\[no-glossary])( *+)\bthis\b( *+)(?!\[/no-glossary])`';
echo $subject.'<br/>';
echo preg_replace($pattern,"$1rabbit$2",$subject); ?>
于 2013-04-07T17:31:10.450 回答
3

玩了一点RegEx模式后,发现Regex PCRE引擎有一定的局限性,于是从另一个角度来看待这个问题:

  1. 匹配所有[no-glossary] this [/no-glossary]this
  2. 过滤结果。

这可以通过以下方式完成preg_replace_callback()

需要 PHP 5.3+

$pattern = "/\[no-glossary\][ ]*\bthis\b[ ]*\[\/no-glossary\]|this/"; 
$html = '<p>Do not replace [no-glossary] this [/no-glossary] replace this.</p>';

$html = preg_replace_callback($pattern, function($match){
    if($match[0] == 'this'){
        return('that');
    }else{
        return($match[0]);
    }
}, $html);

print $html;

如果您没有运行 PHP 5.3+:

$pattern = "/\[no-glossary\][ ]*\bthis\b[ ]*\[\/no-glossary\]|this/"; 
$html = '<p>Do not replace [no-glossary] this [/no-glossary] replace this.</p>';

$html = preg_replace_callback($pattern, 'replace_function', $html);

function replace_function($match){
    if($match[0] == 'this'){
        return('that');
    }else{
        return($match[0]);
    }
}
print $html;

动态的:

$tag = 'no-glossary';
$find = 'this';
$replace = 'that';

$pattern = "/\[$tag\][ ]*\b$find\b[ ]*\[\/$tag\]|$find/"; 
$html = '<p>Do not replace [no-glossary] this [/no-glossary] replace this.</p>';

$html = preg_replace_callback($pattern, function($match) use($find, $replace){
    if($match[0] == $find){
        return($replace);
    }else{
        return($match[0]);
    }
}, $html);

print $html;
于 2013-04-07T17:54:39.017 回答
1

尝试这个:([^\[\]])this([^\[\]])

当然,您需要在“这个”词上应用您真正需要的内容。

于 2013-04-07T16:12:32.950 回答
0

试试这个它只替换this单词

$pattern = '%([^\da-zA-Z]+)this([^\da-zA-Z]+)%si';
$html = '<p>Do not replace [no-glossary]this sdf[/no-glossary] thisreplace<p> replacethis.</p>replace this.</p>';
function Replace1($M){
//print_r($M);
    return $M[1]."that".$M[2];
}
$html = preg_replace_callback($pattern,"Replace1",$html);
print $html;

输出:

<p>Do not replace [no-glossary]that sdf[/no-glossary] thisreplace<p> replacethis.</p>replace that.</p>
于 2013-04-07T16:38:47.573 回答
0

尝试这个:

\b(this)\b(?!(?:(?!\[no-glossary\]).)*?\[/no-glossary\])

这将排除替换this,如果它后面跟着,[/no-glossary]除非它[no-glossary]首先遇到。

于 2013-04-07T16:35:20.360 回答