正则表达式中字符串的否定

时间:2011-09-09 15:25:42

标签: php regex regex-negation

我意识到以前曾经问过类似的东西,但我似乎无法解决我想要做的事情,所以请不要只是认为这是一个骗局。

我在样式{block:string}contents{/block:string}中有一个字符串,可以很容易地与{block:([a-z_-\s]+)}.*{/block:\1}匹配

我想要做的是修改内部。*部分,使它匹配任何字符串之间有{block:[a-z_-\s]+}的字符串,即{block} {/ block

中不应匹配其中有{block}的内容

谢谢!

3 个答案:

答案 0 :(得分:2)

尝试

{block:([a-z_-\s]+)}[^{]*(?!{block:([a-z_-\s]+)}.*{\block:\2})[^}]*{/block:\1}

我在正则表达式上相当平庸,但由[^ {] *和[^}] *语句限制的负面前瞻应该保持你的匹配无标记。

答案 1 :(得分:2)

压缩:m~\{block:([a-z\s_-]+)\}(?:(?!\{/?block:\1\}).)*\{/block:\1\}~xs

Perl中的示例:

$_ = '{block:string}conte{block:string}nts{/block:string}{/block:string}';

if ( m~    # match operator

        \{block: ([a-z\s_-]+) \}   # opening block structure and capt grp 1

        (?:                        # begin non capt grp
            (?! \{/?block: \1 \} )     # negative lookahead, don't want backreffed
                                       # open or closed block struct    
            .                          # ok, grab this character
        )*                         # end group, do 0 or more times (greedy)

        \{/block: \1 \}            # closing block structure matching grp 1 

  ~xs )    # modifiers: expanded, include newlines 

{
   print "matched '$&'\n";
}

输出:
匹配'{block:string} nts {/ block:string}'

答案 2 :(得分:1)

<?php 
$ptn = "%(?:{block:[a-z_\s-]+})(?![^}]*?{block:).*?{/block:[a-z_\s-]+}%";
$str = "... your content here ...";
preg_match_all($ptn, $str, $matches);
print_r($matches);
?>

例如:

$str = "{block:string}test2{/block:string} {block:string}contents{block:string}{block:string}test3{/block:string}{/block:string}{/block:string} sdf ";

会产生:

Array
(
[0] => Array
    (
        [0] => {block:string}test2{/block:string}
        [1] => {block:string}test3{/block:string}
    )
)