Correspondência de expressão regular

Eu quero escrever uma expressão regular que combine qualquer coisa entre

() (()) (()()) ((())) ()()() 

etc.

Todas essas respostas, alegando que você não pode usar padrões para coincidir com uma seqüência de caracteres com parentes nesteds equilibrados são completamente erradas. Não é prático fingir que os padrões combinados pelas modernas linguagens de programação estão restritos a “linguagens regulares” no sentido patológico do livro didático. Assim que você permite backreferences, eles não são. Isso permite que os padrões do mundo real correspondam muito mais do que as versões dos livros didáticos, tornando-os muito mais práticos.

O padrão mais simples para correspondência entre parêntesis equilibrados é \((?:[^()]*+|(?0))*\) . Mas você nunca deve escrever isso , porque é muito compacto para ser lido com facilidade. Você deve sempre escrever com o modo /x para permitir espaços em branco e comentários. Então escreva assim:

 m{ \( # literal open paren (?: # begin alternation group [^()]*+ # match nonparens possessively | # or else (?0) # recursively match entire pattern )* # repeat alternation group \) # literal close paren }x 

Também há muito a ser dito para nomear suas abstrações e desvincular sua definição e sua ordenação de sua execução. Isso leva a esse tipo de coisa:

 my $nested_paren_rx = qr{ (?&nested_parens) (?(DEFINE) (? \( ) (? \) ) (? [^()] ) (? (?&open) (?: (?&nonparens) *+ | (?&nested_parens) ) * (?&close) ) ) }x; 

A segunda forma agora é passível de inclusão em padrões maiores.

Nunca deixe ninguém dizer que você não pode usar um padrão para combinar com algo que é recursivamente definido. Como acabei de demonstrar, você certamente pode.

Enquanto você está nisso, certifique-se de nunca escrever padrões de ruído de linha. Você não precisa, e você não deveria. Nenhuma linguagem de programação pode ser mantida, o que proíbe espaços em branco, comentários, sub-rotinas ou identificadores alfanuméricos. Então use todas essas coisas em seus padrões.

Naturalmente, ajuda a escolher a linguagem certa para esse tipo de trabalho. ☺

Caso você esteja preso a uma linguagem cuja syntax de expressão regular não suporte correspondência recursiva, estou dando a você minha implementação de Javascript simples, a partir da qual você poderá criar o seu próprio no idioma de sua escolha:

 function testBraces(s) { for (var i=0, j=0; i=0; i++) switch(s.charAt(i)) { case '(': { j++ ; break; } case ')': { j-- ; break; } } return j == 0; } 

E aqui você pode brincar com isso: http://jsfiddle.net/BFsn2/

Essa estrutura aninhada não pode ser efetivamente manipulada por expressões regulares. O que você precisa é de uma gramática e um analisador para essa gramática. No seu caso, a gramática é bastante simples. Se você estiver usando python, tente pyparsing ou funcparserlib.

Com pyparsing você pode fazer o seguinte:

 from pyparsing import nestedExpr nestedExpr().parseString( "(some (string you) (want) (to) test)" ).asList() 

Isso retornará uma lista contendo os componentes analisados ​​da string aninhada. O delimitador padrão para nestedExpr é parêntese, portanto, você não precisa fazer nada extra. Se você quiser usar o funcpasrerlib, você pode tentar o seguinte

 from funcparserlib.parser import forward_decl, many, a bracketed = forward_decl() bracketed.define(a('(') + many(bracketed) + a(')')) 

Depois disso, você pode ligar

 bracketed.parse( "( (some) ((test) (string) (you) (want)) (to test))" ) 

e retornará os elementos analisados ​​em uma tupla.

Te desejo boa sorte. Você precisaria de um autômato de estado finito com uma pilha para analisar algo assim. Não pode ser analisado usando apenas regex, já que não é poderoso o suficiente.