zshパラメータ拡張置換パターンは、入力がインラインではなく変数の場合、文字列を異なる方法で解析します。

zshパラメータ拡張置換パターンは、入力がインラインではなく変数の場合、文字列を異なる方法で解析します。

入力がインラインではなく変数である場合、zsh パラメータ拡張置換パターンは文字列を異なる方法で解析します。

これは文字のエスケープと関係があると思われますが、回避方法がわかりません。

以下のコードでは、変数 を使用した最初のパラメータ展開で発生する 、 & を>printf出力から除外する必要があります。*2.5.8versions

ただし、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)一致しない要素を削除するには、フラグを使用します)。

関連情報