2011-04-07 34 views
3

例如,我有一個字符串是這樣的:如何匹配一些嵌套結構與正則表達式?

{% a %} 
    {% b %} 
    {% end %} 
{% end %} 

我想{% a %}{% end %}之間的內容,這是{% b %} {% end %}
我曾經使用{%\ S +%}(。*){%end%}來做到這一點。但是當我添加c:

{% a %} 
     {% b %} 
     {% end %} 
    {% end %} 
{% c %} 
{% end %} 

它不工作......我怎麼能用正則表達式來做到這一點?

+3

它是任意深度的嵌套結構嗎?如果是這樣,那不是一種常規語言。 – eldarerathis 2011-04-07 15:46:17

+0

請不要嘗試。 http://stackoverflow.com/questions/1732348/regex-match-open-tags-except-xhtml-self-contained-tags/1732454 – casablanca 2011-04-07 15:46:44

+2

你可能會有一個更簡單的時間匹配個別元素與正則表達式和使用一個堆棧,以匹配打開/關閉塊。 – GWW 2011-04-07 15:47:22

回答

4

鑑於這種測試數據:

$text = ' 
{% a %} 
    {% b %} 
     {% a %} 
     {% end %} 
    {% end %} 
     {% b %} 
     {% end %} 
{% end %} 
{% c %} 
{% end %} 
'; 

此測試腳本的伎倆:

<?php 
$re = '/ 
    # Match nested {% a %}{% b %}...{% end %}{% end %} structures. 
    \{%[ ]\w[ ]%\}  # Opening delimiter. 
    (?:     # Group for contents alternatives. 
     (?R)    # Either a nested recursive component, 
    |     # or non-recursive component stuff. 
     [^{]*+    # {normal*} Zero or more non-{ 
     (?:    # Begin: "unrolling-the-loop" 
     \{    # {special} Allow a { as long 
     (?!    # as it is not the start of 
      %[ ]\w[ ]%\} # a new nested component, or 
     | %[ ]end[ ]%\} # the end of this component. 
     )    # Ok to match { followed by 
     [^{]*+   # more {normal*}. (See: MRE3!) 
    )*+    # End {(special normal*)*} construct. 
    )*+     # Zero or more contents alternatives 
    \{%[ ]end[ ]%\}  # Closing delimiter. 
    /ix'; 
$count = preg_match_all($re, $text, $m); 
if ($count) { 
    printf("%d Matches:\n", $count); 
    for ($i = 0; $i < $count; ++$i) { 
     printf("\nMatch %d:\n%s\n", $i + 1, $m[0][$i]); 
    } 
} 
?> 

這裏是輸出:

2 Matches: 

Match 1: 
{% a %} 
    {% b %} 
     {% a %} 
     {% end %} 
    {% end %} 
     {% b %} 
     {% end %} 
{% end %} 

Match 2: 
{% c %} 
{% end %} 

Ë dit:如果您需要匹配具有多個單詞char的開始標記,請將\w標記中的兩個出現替換爲(?!end)\w++(如在tchrist的出色答案中正確實施)。

+0

+1,RegEx的真棒格式 – drudge 2011-04-07 18:52:34

0

你在找什麼叫做recursive regex。 PHP支持它使用(?R)

我對它不夠熟悉,無法幫助您理解模式本身,但希望這是一個正確的方向。

2

下面是一個適用於您的數據集的方法在Perl中的演示。在PHP中也一樣。

#!/usr/bin/env perl 

use strict; 
use warnings; 

my $string = <<'EO_STRING'; 
    {% a %} 
      {% b %} 
      {% end %} 
     {% end %} 
    {% c %} 
    {% end %} 
EO_STRING 


print "MATCH: $&\n" while $string =~ m{ 
    \{ % \s+ (?!end) \w+ \s+ % \} 
    (?: (?: (?! % \} | % \}) .) | (?R))* 
    \{ % \s+ end \s+ % \} 
}xsg; 

運行時,產生這樣的:

MATCH: {% a %} 
      {% b %} 
      {% end %} 
     {% end %} 
MATCH: {% c %} 
    {% end %} 

還有一些其他的方式來寫。你可能還有其他的限制,你沒有顯示,但這應該讓你開始。

相關問題