Por que '[a-z] *' corresponde a cadeias não alfabéticas?

8

Eu tenho um arquivo alphanum com estas duas linhas:

123 abc
this is a line

Estou confuso sobre o porquê, quando executo sed 's/[a-z]*/SUB/' alphanum , recebo a seguinte saída:

SUB123 abc
SUB is a line

Eu estava esperando:

123 SUB
SUB is a line

Encontrei uma correção (use sed 's/[a-z][a-z]*/SUB/' ), mas não entendo porque funciona e a minha não.

Você pode ajudar?

    
por Fakher Mokadem 20.05.2018 / 16:45

2 respostas

28

O padrão [a-z]* corresponde a zero ou mais caracteres no intervalo a a z (os caracteres reais dependem da localidade atual). Não há zero tais caracteres no início da string 123 abc (ou seja, o padrão corresponde) e também quatro deles no início de this is a line .

Se você precisar de pelo menos uma correspondência, use [a-z][a-z]* ou ative as expressões regulares estendidas com sed -E e use [a-z]+ .

Para visualizar onde o padrão corresponde, adicione parênteses em torno de cada correspondência:

$ sed 's/\([a-z]*\)/()/' file
()123 abc
(this) is a line

Ou com uma correspondência repetida:

$ sed 's/\([a-z]*\)/()/g' file
()1()2()3() (abc)
(this) (is) (a) (line)

Compare esse último resultado com

$ sed -E 's/([a-z]+)/()/g' file
123 (abc)
(this) (is) (a) (line)
    
por 20.05.2018 / 16:49
12

Porque * corresponde a zero ou mais repetições do átomo anterior, e todos os mecanismos de regex tentam encontrar a primeira correspondência. Há uma substring de exatamente zero letras no início de sua string, então é onde ela corresponde. No caso em que a string começa com uma letra, o * corresponde a tantos quantos pode, mas isso é secundário para encontrar a correspondência mais à esquerda.

Correspondências de tamanho zero podem ser um pouco problemáticas e, como você viu, a solução é modificar o padrão para que ele exija pelo menos um caractere. Com regexes estendidos, você poderia + para isso: sed -E 's/[a-z]+/SUB/'

Por diversão, tente:

echo 'less than 123 words' | sed 's/[0-9]*/x/g'
    
por 20.05.2018 / 16:49