入力がインラインではなく変数である場合、zshパラメーター拡張置換パターンは文字列を異なる方法で解析します。
キャラクターのエスケープと関係があると思いますが、どうやって回避するのかわかりません。
以下のコードでは、>
、*
&2.5.8
は、変数versions
を使用した最初のパラメーター展開で発生するprintf出力からフィルターで除外する必要があります。
ただし、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:]]##}}
$(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の周りに不要な_${}
_が1つありましたが、これは上記で削除されています)
デフォルトのzsh
シェルでは、パラメータ展開はIFS
による分割を避けるために引用符を付ける必要はありません(ただし、どちらも害はありません)。引用符で囲まれていないコマンド置換はIFS
で分割される可能性があるため、引用符で囲まないようにする必要があります。
マニュアルzshexpn(1)
:
_
PARAMETER EXPANSION
_特に、引用符で囲まれていないパラメータの単語は、オプション_
SH_Word_SPLIT
_が設定されていない限り、空白で自動的に分割されないことに注意してください。詳細については、以下のこのオプションへの参照を参照してください。これは他のシェルとの重要な違いです。ただし、他のシェルと同様に、引用符で囲まれていないパラメーターの展開からnullワードが削除されます。_
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)
_フラグを使用して、一致しない要素を削除します)。