Substituição do regex da digitação de dígitos

2

Eu estou lutando um pouco com esse regex de substituição, eu não conseguia entender por que ele está se comportando dessa maneira. O que eu quero fazer é substituir todos os dígitos numéricos após o último / :

str="aa/a0b0/42"
echo ${str/%[[:digit:]]*/5}
echo ${str/%[0-9]*/5}

Os dois echo produzem aa/a5 como saída. A saída esperada seria aa/a0b0/5 .

Estou ciente de que posso usar ferramentas como sed e awk para resolver o meu problema, e sei como fazê-lo, mas estou procurando uma solução somente de bash.

Eu gostaria de entender por que o [0-9]* está se expandindo para 0b0 / 42 em vez de apenas dígitos numéricos.

O % no meu regex é para fazer substituição de back-end .

    
por Kira 29.10.2015 / 19:28

1 resposta

5

Porque essa é uma correspondência de padrões , não uma expressão regular.

[[:digit:]]* significa um dígito seguido por qualquer string, por isso 0b0/42 correspondido. É um dígito, 0 , seguido por uma string, b0/42 .

Agora, em bash , com extglob ativado, você pode usar +(pattern-list) para corresponder a uma ou mais ocorrências de um padrão:

$ shopt -s extglob
$ printf '%s\n' "${str/%+([[:digit:]])/5}"
aa/a0b0/5

Você tem essa sintaxe por padrão em ksh , que bash copiou de.

Em zsh , embora você possa usar esses ksh padrões com setopt kshglob ou usar zsh own extendedglob ( [[:digit:]]## ), também é possível executar regex replace com o regex-replace função :

$ str="aa/a0b0/42"
$ autoload -U regexp-replace
$ regexp-replace str '[[:digit:]]+$' 5
$ print -rl -- $str
aa/a0b0/5

Se você garantir que a parte após o último / sempre seja igual, você poderá fazê-lo POSIXLY:

printf '%s/%s\n' "${str%/*}" 5
    
por 29.10.2015 / 19:39