如果输入是变量而不是内联变量,则 zsh 参数扩展替换模式会以不同的方式解析字符串。
我认为这与字符转义有关,但不知道如何解决它。
在下面的代码中,>
, *
&2.5.8
应该从 printf 输出中过滤掉,这发生在使用变量 的第一个参数扩展中versions
。
但是当curl
调用是内联的时候,上面的3个值就不会被过滤掉。
如何内联调用curl
但仍过滤掉 3 个值?
#!/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:]]##}}
答案1
引用$(command)
替换:
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:]]##}
${}
( expn 周围有一个多余的多余部分,已在上面删除)
在默认zsh
shell 中,参数扩展不需要引用来避免分裂IFS
(但这也不会造成伤害)。不加引号命令替换会被 分割IFS
,因此必须引用以避免这种情况。
手册zshexpn(1)
:
PARAMETER EXPANSION
SH_WORD_SPLIT
特别要注意的是,除非设置了该选项,否则未加引号的参数的单词不会自动在空格上分割;有关更多详细信息,请参阅下面对此选项的引用。这是与其他 shell 的一个重要区别。然而,与其他 shell 一样,未加引号的参数扩展中会忽略空字。
COMMAND SUBSTITUTION
如果替换未用双引号括起来,则使用参数将输出分解为单词
IFS
。
此外,可能还有其他方法可以删除这些字符串,例如
printf -- '%s\n' ${${=versions}:#([*+>-]|2.5.8)}
可以与不带引号的命令替换一起使用:
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)}
上面使用了形式的参数扩展${name:#pattern}
。手册说:
${name:#pattern}
如果模式与 name 的值匹配,则替换为空字符串;否则,只需替换 name 的值即可。如果 name 是一个数组,则删除匹配的数组元素(使用该(M)
标志删除不匹配的元素)。