Um padrão de substituição de expansão de parâmetro zsh analisa a string de maneira diferente se a entrada for uma variável em vez de embutida.
Presumo que tenha algo a ver com a fuga do personagem, mas não tenho certeza de como contornar isso.
No código abaixo, >
, *
& 2.5.8
deve ser filtrado da saída printf, que ocorre na primeira expansão do parâmetro usando a variável versions
.
Mas quando a curl
chamada está embutida, os 3 valores acima não são filtrados.
Como posso incorporar a curl
chamada e ainda assim filtrar os 3 valores?
#!/usr/bin/env zsh
setopt EXTENDED_GLOB
# variable: 3 values are correctly filtered out
versions=$(curl '--silent' '--location' 'https://api.sdkman.io/2/candidates/groovy/darwin/versions/list?current=2.5.8&installed=2.5.8')
printf -- '%s\n' ${${(Z+n+)versions//[*+>][ *+>]# [[:graph:]]##}}
# inlined: 3 values are not filtered out
printf -- '%s\n' ${${(Z+n+)$(curl '--silent' '--location' 'https://api.sdkman.io/2/candidates/groovy/darwin/versions/list?current=2.5.8&installed=2.5.8')//[*+>][ *+>]# [[:graph:]]##}}
Responder1
Cite a $(command)
substituição:
printf -- '%s\n' ${(Z+n+)"$(curl '--silent' '--location' 'https://api.sdkman.io/2/candidates/groovy/darwin/versions/list?current=2.5.8&installed=2.5.8')"//[*+>][ *+>]# [[:graph:]]##}
(Havia um extra desnecessário ${}
em torno da expn, que foi removido acima)
Em um zsh
shell padrão,expansão de parâmetrosnão precisa de citação para evitar divisão IFS
(mas também não vai doer). Sem citaçãosubstituição de comandoestá sujeito a divisão por IFS
, portanto, é necessário fazer citações para evitar isso.
O manual zshexpn(1)
:
PARAMETER EXPANSION
Observe em particular o fato de que palavras com parâmetros sem aspas não são automaticamente divididas em espaços em branco, a menos que a opção
SH_WORD_SPLIT
seja definida; veja as referências a esta opção abaixo para obter mais detalhes. Esta é uma diferença importante em relação a outros shells. No entanto, como em outros shells, palavras nulas são omitidas das expansões de parâmetros sem aspas.
COMMAND SUBSTITUTION
Se a substituição não estiver entre aspas duplas, a saída será dividida em palavras usando o
IFS
parâmetro.
Além disso, pode haver outras maneiras de remover essas strings, por exemplo
printf -- '%s\n' ${${=versions}:#([*+>-]|2.5.8)}
que poderia ser usado com uma substituição de comando sem aspas:
printf -- '%s\n' ${$(curl '--silent' '--location' 'https://api.sdkman.io/2/candi'\
'dates/groovy/darwin/versions/list?current=2.5.8&installed=2.5.8'):#([*+>-]|2.5.8)}
O texto acima usa uma expansão de parâmetro no formato ${name:#pattern}
. O manual diz:
${name:#pattern}
Se o padrão corresponder ao valor de name, substitua a string vazia; caso contrário, basta substituir o valor do nome. Se name for um array, os elementos correspondentes do array serão removidos (use o(M)
sinalizador para remover os elementos não correspondentes).