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