Existe alguma expansão concisa de parâmetro de expressão regular zsh para substituir a última correspondência de um padrão?
Conheço uma maneira muito feia de fazer isso, mas preferiria uma sintaxe mais limpa e concisa:
# param, pattern & replacement are placeholders below for real values
${(*S)param/%pattern(#b)(*)/replacement${match[1]}}
O que habilita extended_glob, escolhe a correspondência mais curta, compara o padrão com o final do valor de $param
, especifica o padrão, habilita referências anteriores, salva o texto posterior à última correspondência do padrão em uma referência anterior e, então, substitui a correspondência pela minha substituição, usando a referência anterior para restabelecer o texto posterior à correspondência.
Se por última ocorrência você quer dizer a última depois de ter procurado por elas da esquerda para a direita como
${param//pattern/replacement}
faz (o que não é o que sua tentativa faz), você pode fazer:Uma função que substitui a n- ésima ocorrência (possivelmente contada a partir da última quando n é negativo) poderia ser escrita como:
Para ser chamado, por exemplo, como:
Não há uma maneira explícita de selecionar a última correspondência. Mas você pode fazer a correspondência
*
seguida pelo seu padrão: então seu padrão será a última correspondência, já que*
corresponde ao prefixo mais longo possível que é seguido pelo seu padrão. Use ob
sinalizador globbing para obter acesso às partes da string correspondida na substituição.Isso precisa
extended_glob
ser habilitado. Com zsh ≥5.9, você pode ativá-lo com o*
parâmetro expansion flag .Por exemplo, o snippet a seguir corresponde
a1b2c3d
ao padrão(#b)(*)([0-9])
.(#b)
faz com que os grupos entre parênteses a seguir registrem o que eles correspondem em$match
. (As posições também estão disponíveis em$mbegin
e$mend
se você precisar delas.)*
corresponde ao prefixo mais longo, então[0-9]
corresponde ao último dígito. A substituição mantém o prefixo correspondido por*
, substitui o dígito por outra coisa e mantém o sufixo não correspondido, então o snippet geraa1b2c-d
.No zsh ≥5.9, você não precisa ter certeza de que ele
extended_glob
está ativo.