Por que [0-9] * corresponde onde não há algarismos?

6

então o comando é:

echo "abc 123" | sed "s/[0-9]*/h/g"

e estou recebendo a saída como

hahbhch h

como estou obtendo essa saída?

a saída que eu esperava que fosse é abc h

que estou recebendo por este comando:

echo "abc 123" | sed "s/[0-9][0-9]*/h/g"

alguém pode explicar isso ...

    
por sidharthanup 23.12.2015 / 16:22

2 respostas

18

O * significa zero ou mais correspondências e corresponde o mais rápido possível. Se você executar esse comando sem o sinalizador g (o que significa que sed será interrompido após a primeira substituição), você obterá como saída habc 123 . Isso ocorre porque ele começa a ler da esquerda para a direita e, como não conseguiu corresponder a a , ele simplesmente coincide com o início da linha e, em seguida, para lá.

Usando o sinalizador global ( g ), ele continuará tentando corresponder ao restante da string e, como * corresponde à string vazia quando não pode corresponder a nada, ela colocará h toda vez que não pode corresponder a mais números.

Observe que sua segunda tentativa é equivalente a sed "s/[0-9]\+/h/" . Aqui + significa uma ou mais correspondências, o que significa que não corresponderá à string vazia quando não encontrar um número para substituir.

    
por 23.12.2015 / 16:27
3

A resposta está relacionada ao modo como Expressões Regulares são tratadas no sed. Expressões regulares ou REs podem se tornar muito complexas e há uma compensação entre o poder do que você pode fazer com elas e a complexidade da sintaxe. Diferentes linguagens de programação fizeram escolhas diferentes sobre quanto poder e, portanto, complexidade, eles querem suportar. Sed é muito poderoso e, portanto, um pouco mais complexo do que você poderia esperar. Para chegar à resposta, o * corresponde a uma sequência de zero ou mais instâncias do token anterior. No seu caso, o token anterior é [0-9], o que significa qualquer dígito. Sed está percebendo que há uma cadeia de dígitos com comprimento zero antes e depois de cada caractere na string de entrada. Isso parece bastante intuitivo até você se acostumar com isso. Você notou uma maneira comum de corrigir o problema que é usar / [0-9] [0-9] * / que é interpretado como um dígito seguido por zero ou mais dígitos. Outra solução é substituir * por +. O + corresponde a uma sequência de um ou mais do token anterior. Então o comando completo é:

echo "abc 123" | sed "s/[0-9]+/h/g"

Você pode ler sobre o comando sed usando o manual online (apenas google man sed) ou se os manuais estiverem instalados no seu sistema basta executar o comando "man sed"

    
por 23.12.2015 / 16:46