正则表达式替换标签之间没有包含的单词(非html)

时间:2013-04-07 15:55:14

标签: php xml regex

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

我想替换不在[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. 在正确替换的第二个单词前删除了空格。

5 个答案:

答案 0 :(得分: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); ?>

答案 1 :(得分:2)

在使用RegEx模式玩一点之后,我发现Regex PCRE引擎有一些限制,所以我从另一个角度来看问题:

  1. 匹配所有[no-glossary] this [/no-glossary]this
  2. 过滤结果。
  3. 可以使用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;
    

答案 2 :(得分:1)

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

当然,你需要在'this'这个词上应用你真正需要的东西。

答案 3 :(得分:0)

试试这个:

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

如果this后面跟[/no-glossary],则会排除[no-glossary],除非先遇到{{1}}。

答案 4 :(得分: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>