Corresponder expressão regular entre delimitadores

1

Eu tenho um arquivo com várias linhas diferentes. Eu estou procurando por linhas que contenham (mais ou menos) padrão como este:

\[.*<.*>.*\]

Em outras palavras, quero as linhas que têm <something> entre []. Exemplos podem ser:

Line with [ <matching>|<pattern>]
A line <that> does[not]<match>[]
But [this[<should>]be matched] too
[match [me] <buddy>]

Os únicos caracteres permitidos entre < > são caracteres alfanuméricos e sublinhados.

Eu tentei o regexp acima e sua versão preguiçosa, mas não funcionou. Qual é o regexp adequado?

    
por MatthewRock 27.08.2015 / 14:47

4 respostas

2

Se os seus pares [ , ] forem sempre correspondidos e você não cruzar [...] s com <...> , e seu grep suportar a opção -P (como o GNU grep quando construído com suporte a PCRE), você pode fazer:

grep -P '>(?!((?:[^]]|\[(?1)\])*)$)'

Ou seja, procure um > que não seja seguido apenas pelos pares [...] correspondentes. Ele usa o mecanismo de correspondência recursiva de (?1) do PCREs.

    
por 27.08.2015 / 15:13
1

POSIXly, você poderia fazer isso com sed :

sed  '
  h; # make a copy of the pristine line on the hold space
  :1
    /\[[^]]*<[^]]*>[^]]*]/{
      # found a [...<x>...]
      g; # retrieve our saved copy and branch off
      b
    }
    s/\[\([^]]*\)]//g; # remove inner [...]s
    # and loop if that s command was successful
  t1
  # no [...] left to remove, discard this line.
  d'

Ou seja, remova os pares de [...] , começando pelos internos até encontrar um <...> dentro de um par.

(em sistemas Solaris ou muito antigos, remova os comentários, pois o Solaris sed permite apenas comentários no início das linhas).

    
por 27.08.2015 / 15:43
0

Esse padrão com correspondência tardia (precisando de -P AFAIU) funciona para mim:

grep -P '\[[^\]]*?<.*>.*?\]'
    
por 27.08.2015 / 14:57
0

Eu criei a seguinte solução:

grep -P '\[[^.\]]*<.*>[^.\[]*\]' filename

Em outras palavras, combinamos um par de [e] com um par de < e > entre com as seguintes restrições:

  1. entre [] não deve fechar e abrir o colchete antes e depois da < > par "[^. \]] *".
  2. dentro de < > deve ter pelo menos um caractere.

Esta solução também é muito mais rápida que o regex com quantificadores preguiçosos.

    
por 27.08.2015 / 14:50