expressões regulares gananciosas e preguiçosas (questão de compreensão)

4

Eu estou ensinando a mim mesmo expressões regulares, e fiquei preso em repetições gananciosas x preguiçosas.

O que eu descobri até agora é que

  • »ganancioso« significa que o RegExp procura o maior número possível de correspondências, onde
  • »preguiçoso« significa que o RegExp procura as menores correspondências possíveis

A maioria dos artigos que encontrei lidam com a) usando-a em uma linguagem de programação, enquanto eu estou preso aqui com grep e egrep ou b) use grep -P para ativar Perl Mode ; mas como eu não tenho nenhum conhecimento sobre o Perl, no entanto, isso não é muito útil para mim.

Minha pergunta de compreensão : cheguei a esse método de marreta:

  • as repetições preguiçosas procurarão a correspondência mais curta possível
  • se os resultados forem muito longos → diminua o tom do repetidor com ?
  • se os resultados ainda forem muito longos → procure outra solução

Isso foi o que consegui descobrir por meio de exemplos e experimentos com código HTML, nos quais obtive alguns, mas não resultados impressionantes.

Eu ficaria grato se alguém pudesse me dizer se e onde eu perdi alguns pontos importantes com o meu resumo.

    
por erch 10.04.2013 / 03:29

2 respostas

3

Não é a correspondência mais curta possível, apenas uma correspondência curta. Modo Greedy tenta encontrar a última correspondência possível, modo preguiçoso a primeira correspondência possível. Mas a primeira correspondência possível não é necessariamente a mais curta.

Pegue a string de entrada foobarbaz e o regexp o.*a (greedy) ou o.*?a (lazy).

A correspondência mais curta possível nesta string de entrada seria oba .

No entanto, o RegExp procura correspondências da esquerda para a direita, portanto, o o encontra o primeiro o em foobarbaz . E se o resto do padrão produzir uma correspondência, é onde fica.

Após o primeiro o , .* (ganancioso) come obarbaz (a string inteira) e depois retrocede para corresponder ao restante do padrão ( a ). Assim, ele encontra o último a em baz e acaba combinando com oobarba .

Após o primeiro o , .*? (lazy) não come a string inteira, em vez disso, procura a primeira ocorrência do resto do padrão. Primeiro, ele vê o segundo o , que não corresponde a a , depois vê b , que não corresponde a a , depois vê a , que corresponde a a , e porque é preguiçoso é onde ele pára. (e o resultado é ooba , mas não oba )

Portanto, embora não seja O mais curto possível, é mais curto do que a versão gulosa.

    
por 10.04.2013 / 12:17
2

"Perl Mode" refere-se a expressões regulares compatíveis com perl (PCRE). Coloquialmente falando , este é o estilo de expressão regular usado nativamente pela maioria das linguagens modernas, se elas tiverem expressões regulares nativas - Perl, Python, Ruby, PHP, JavaScript, Java - embora possa haver pequenas diferenças entre eles; tecnicamente, PCRE é derivado, mas não é idêntico ao mecanismo perl regexp, etc, mas se você pode usar regexps em um dos essas linguagens são 99% iguais nas outras. Ele predomina onde é uma opção, porque é uma melhoria no estilo antigo, agora distinguido como regexps POSIX, que é o modo padrão das ferramentas da velha escola, como o grep.

O não-ganancioso, também conhecido como. O modificador preguiçoso não é significativo no contexto do uso do grep para corresponder as linhas. Isso ocorre porque não pode haver nenhuma linha completa que corresponda a uma expressão preguiçosa que uma gananciosa não irá igualar e vice-versa. No entanto, você pode ver a diferença se usar a opção -o , que mostra o conteúdo do segmento correspondente e não as linhas inteiras (nb. Isso é um pouco diferente do que o --color faz):

»echo "123 abc 456 def 789" > eg.txt
»grep -o -P "(\d+\s[A-Za-z]+\s)+" eg.txt
123 abc 456 def 
»grep -o -P "(\d+\s[A-Za-z]+\s)+?" eg.txt
123 abc 
456 def 
»grep -o -P "\d+\s[A-Za-z]+\s\d+" eg.txt
123 abc 456
»grep -o -P "\d+\s[A-Za-z]+\s\d+?" eg.txt
123 abc 4
56 def 7

Se você estiver usando o grep dessa maneira (com -o ), a ganância faz diferença. Se você estiver usando o grep para corresponder linhas completas que contenham um padrão, o ? não-ganancioso não importará de uma forma ou de outra.

Resumindo: um jogo ganancioso corresponde o máximo possível, um jogo não ganancioso corresponde o mínimo possível.

    
por 10.04.2013 / 10:45