2013-06-29 2 views
4

я придумал регулярное выражение строки, которая анализирует данный текст на 3 категории:Как обрабатывать вложенные круглые скобки с регулярным выражением?

  • в скобках
  • в скобках
  • ни.

Как это:

\[.+?\]|\(.+?\)|[\w+ ?]+ 

Мое намерение состоит в том, чтобы использовать только самый наружный оператор. Таким образом, учитывая a(b[c]d)e, раскол будет:

a || (b[c]d) || e 

Он отлично работает, данные круглые скобки внутри скобок, или скобок внутри скобок, но ломается, когда есть скобки внутри скобок и скобки внутри скобок. Например, a[b[c]d]e распределятся

a || [b[c] || d || ] || e. 

Есть ли способ, чтобы справиться с этим, используя регулярные выражения в одиночку, не прибегая к использованию кода для подсчета количества открыто/закрыто скобки? Благодаря!

+0

Почему вы не можете создать свой собственный парсер? –

+2

На каком языке вы используете этот форум? Регулярные выражения могут (теоретически) не анализировать вложенные структуры. Если вы используете .NET или Perl/PCRE, вам может быть повезло, потому что у них есть некоторые дополнительные функции, которые могут. –

+0

Язык вложенных круглых скобок не является регулярным. Следовательно, «регулярные» выражения (в математическом смысле этого слова) не соответствуют задаче. период. – Bwmat

ответ

9

Стандартные Регулярные выражения недостаточно сложны, чтобы соответствовать вложенным структурам, подобным этому. Лучший способ приблизиться к этому - это, вероятно, пересечение строки и отслеживание пар открытия/закрытия.


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

$str = "[hello [world]] abc [123] [xyz jkl]"; 

my @matches = $str =~ /[^\[\]\s]+ | \[ (?: (?R) | [^\[\]]+)+ \] /gx; 

foreach (@matches) { 
    print "$_\n"; 
} 
 
[hello [world]] 
abc 
[123] 
[xyz jkl] 

EDIT: Я вижу, что вы используете Python; выписка pyparsing.

+1

+1 отлично не проповедующий пост. –

0

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

def nested_matcher (n): 
    # poor man's matched paren scanning, gives up after n+1 levels. 
    # Matches any string with balanced parens or brackets inside; add 
    # the outer parens yourself if needed. Nongreedy. Does not 
    # distinguish parens and brackets as that would cause the 
    # expression to grow exponentially rather than linearly in size. 
    return "[^][()]*?(?:[([]"*n+"[^][()]*?"+"[])][^][()]*?)*?"*n 

import re 

p = re.compile('[^][()]+|[([]' + nested_matcher(10) + '[])]') 
print p.findall('a(b[c]d)e') 
print p.findall('a[b[c]d]e') 
print p.findall('[hello [world]] abc [123] [xyz jkl]') 

Этот выход будет

['a', '(b[c]d)', 'e'] 
['a', '[b[c]d]', 'e'] 
['[hello [world]]', ' abc ', '[123]', ' ', '[xyz jkl]'] 
Смежные вопросы