2014-10-03 2 views
0

Я обычно используя следующее регулярное выражение для сбалансированного соответствияПовышение Perl регулярное выражение для сбалансированного соответствие

my $np; 
$np = qr{ 
       \{ 
       (?: 
         (?> [^\{\}]+) 
        | 
         (??{ $np }) 
       )* 
       \} 
      }x; 

, как, например,

my $text = "{string{string1}{string2}}"; 
$text =~ /($np)/; 

Вопрос заключается в том, может ли он быть расширен таким образом, что совпадает также, когда string и т. д. содержит } или {, которым предшествует обратная косая черта. Это означает, что экранированные фигурные скобки следует игнорировать (обрабатывать как любой другой символ), когда выполняется сбалансированное сопоставление.

+1

@ M42: по ссылке вопрос, является общим о подходящих сбалансированных пар скобок. Это не помогает этому плакату, который уже знает, как это сделать, но не может сопоставлять * escape-фигуры * как обычный текст между согласованными. – Borodin

+0

Вы действительно используете 'NSRegularExpression'? В этом случае это не Perl. – Borodin

ответ

3

Несомненно. Все, что вам нужно сделать, это изменить «любой другой символ» выражение в один, который будет принимать сбежавших брекеты, а также «ничего, кроме фигурной скобкой»

(?> (?: \\[()] | [^{}])+ ) 

Отметим также, что (??{ $np }) конструкция уже давно и если у вас есть версия 10 или более поздняя версия Perl 5, вы можете использовать встроенный механизм recursion, в котором (?R) будет возвращать все выражение с самого начала.

use strict; 
use warnings; 
use 5.010; 

my $np = qr{ 
    \{ 
    (?: 
     (?> 
     (?: \\\\ | \\} | \\} | [^{}])* 
    ) 
    | 
     (?R) 
    )* 
    \} 
}xs; 

my $text = '{string{string1 \} test}{string2}}'; 
$text =~ /($np)/; 

say $1; 

выход

{string{string1 \} test}{string2}} 

Пожалуйста, обратите внимание, что я не верю, что "не отступать" не построить (?> ...) полезно здесь. Промежуточная строка была указана так, чтобы все, что было после , должно было соответствовать следующему токену или концу строки, и нет никаких неприличных подстановочных знаков. Но я уверен, что он не делает никакого вреда, так что я оставил его.


Update

Для обеспечения сбежавшего открытия брекета перед тем первой регулярной скобки, то проще написать отдельный regex для «Обычный символ», который является чем угодно, кроме открывающей или закрывающей скобки или чего-то скрытого.

Как этот

use strict; 
use warnings; 
use 5.010; 

my $reg_char = qr/(?: \\. | [^{}])/xs; # Define what *isn't* a brace 

my $np = qr{ 
    \{ 
    (?: 
     (?> $reg_char*) 
    | 
     (?R) 
    )* 
    \} 
}x; 

my $text = 'aaa \{ bbb {string{string1 \} test}{string2}}'; 
die unless $text =~/$reg_char* ($np) /x; 

say $1; 

выход

{string{string1 \} test}{string2}} 
+0

Неявно упоминается в вопросе, но вам, вероятно, также необходимо проверить, не открыта ли открывающая скобка. Кроме того, двойная обратная косая черта перед фигурной скобкой, вероятно, сбежала с обратной косой чертой и не должна была выходить из скобки ... –

+0

Да, точно, но я решил, что могу сделать это с помощью отрицательного lookbehind '(? highsciguy

+0

@highsciguy: Если вы ожидаете сбежавших открытых брекетов * вне * любого заключенного в квадратные скобки текста, то я думаю, что отрицательный внешний вид - самый простой выбор. В противном случае вам нужно будет добавить выражение «регулярный символ» * перед открывающей скобкой. Я добавил скрытую обратную косую черту как один из обычных символов, которые будут пропущены, так как это не повредит. – Borodin

Смежные вопросы