如果輸入是變數而不是內聯變量,則 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)
標誌刪除不符合的元素)。