Получение содержимого квадратных скобок с регулярным выражением, включая вложенные - PullRequest
2 голосов
/ 05 апреля 2010

Есть ли способ получить это:

[one[two]][three]

И извлечь это с помощью регулярного выражения?

Array (
    [0] => one[two]
    [1] => two
    [2] => three

Ответы [ 4 ]

4 голосов
/ 05 апреля 2010

Для PHP вы можете использовать рекурсию в регулярных выражениях, которые почти дают вам то, что вы хотите:

$s = 'abc [one[two]][three] def';
$matches = array();
preg_match_all('/\[(?:[^][]|(?R))*\]/', $s, $matches);
print_r($matches);

Результат:

Array
(
    [0] => Array
        (
            [0] => [one[two]]
            [1] => [three]
        )

)

Для чего-то более сложного, возможно, лучше не использовать регулярные выражения.

0 голосов
/ 06 апреля 2010

В регулярном выражении Perl 5.10 вы можете использовать именованный возврат и рекурсивную подпрограмму, чтобы сделать это:

#!/usr/bin/perl

$re = qr  /
     (                      # start capture buffer 1
        \[                  #   match an opening brace
        (                   # capture buffer 2
        (?:                 #   match one of:
            (?>             #     don't backtrack over the inside of this group
                [^\[\]]+    #       one or more non braces
            )               #     end non backtracking group
        |                   #     ... or ...
            (?1)            #     recurse to bracket 1 and try it again
        )*                  #   0 or more times.
        )                   # end buffer 2
        \]                  #   match a closing brace
     )                      # end capture buffer one
    /x;


print "\n\n"; 

sub strip {
my ($str) = @_;
while ($str=~/$re/g) {
    $match=$1; $striped=$2;
    print "$striped\n";
    strip($striped) if $striped=~/\[/;
    return $striped;
}
}


$str="[one[two]][three][[four]five][[[six]seven]eight]";

print "start=$str\n";

while ($str=~/$re/g) { 
    strip($1) ;
}

Выход:

start=[one[two]][three][[four]five][[[six]seven]eight]
one[two]
two
three
[four]five
four
[[six]seven]eight
[six]seven
six
0 голосов
/ 05 апреля 2010
#!/usr/bin/perl
use Data::Dumper;
@a = ();
$re = qr/\[((?:[^][]|(??{$re}))*)\](?{push@a,$^N})/;
'[one[two]][three]' =~ /$re*/;
print Dumper \@a;
# $VAR1 = [
#           'two',
#           'one[two]',
#           'three'
#         ];

Не точно , что вы просили, но это вроде выполнимо с (ir) расширениями регулярных выражений. (Perl 5.10 (?PARNO) может заменить использование (??{CODE}).)

0 голосов
/ 05 апреля 2010

Вы можете применить регулярное выражение с циклом, например,

  1. Совпадение всех \[([^\]]*)\].
  2. Для каждого соответствия замените \x01 на [ и \x02 на ] и выведите результат.
  3. Заменить все \[([^\]]*)\] на \x01$1\x02 ( предупреждение : предполагается, что \x01 и \x02 не используются в строке.)
  4. Повторяйте 1, пока не будет совпадения.

Но я бы написал строковый сканер для этой проблемы:).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...