grep até parênteses correspondentes

5

Eu tenho um arquivo como este: -

pin(ABC) {  
              a b c d e f {  
              abc  
              }  
             }  
pin(XYZ) {  
              g h i j k  {  
                      j k {  
                        cg {  
                     }  
                    }  
                   }  
                  }  
abcd pqrs rstu  
mango banana tree  
pin(PQR) {  
               mango  
         }  

Agora eu quero entender o texto assim: -
quando eu dou ABC como entrada, então a saída deve ser um arquivo chamado ABC com o conteúdo de "pin (ABC) {" até o parêntese de correspondência "}" assim: -

pin(ABC) {  
              a b c d e f {  
              abc  
              }  
             }  

quando eu dou PQR a saída deve ser um arquivo chamado PQR com este conteúdo: -

pin(PQR) {  
               mango  
         }  

& assim por diante para qualquer palavra que esteja dentro do pin ()
Uma maneira de fazer isso é utilizar o texto de "pin (ABC) até o próximo nome" pin "e direcionar a saída para o arquivo chamado" ABC ", ele funciona apenas para ABC, mas falha no caso de PQR & XYZ. Como fazer isso.

    
por yogendra singh 31.07.2014 / 15:28

1 resposta

5
$ pcregrep -Mo 'pin\(ABC\) (\{([^{}]++|(?1))*\})' file
pin(ABC) {
              a b c d e f {
              abc
              }
             }

Se você não tem pcregrep mas tem o GNU grep e ele foi construído com suporte a padrões PCRE e seu arquivo não é muito grande e não contém caracteres NUL, você pode fazer:

grep -zPo 'pin\(ABC\) (\{([^{}]++|(?1))*\})' file

Aqueles ( pcregrep e grep -P ) estão usando padrões PCRE que suportam operadores regex recursivos.

pcregrep -M ativa o modo de múltiplas linhas (onde pcregrep pode extrair várias linhas conforme necessário ao corresponder ao regexp) e grep -z informa que os registros são separados por NUL em vez de linhas .

O truque acima está no operador (?1) , o que significa os regexps dentro do primeiro grupo paren , por isso temos um regexp recursivo: estamos combinando { seguido por uma seqüência de 0 ou mais ( * ) seqüências de caracteres não-chave ( [^{}]++ , ++ sendo a versão possessiva de + ) ou o regexp na% externa(...) novamente ( { seguido por ...).

Veja a página man de pcrepattern para detalhes. Isso é copiado quase literalmente de um exemplo lá.

Usando perl :

perl -l -0777 -ne 'print $& while /pin\(ABC\) (\{([^{}]++|(?1))*\})/g'

(como para grep , ele pega todo o arquivo na memória).

    
por 31.07.2014 / 15:41