web-dev-qa-db-ja.com

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

入力がインラインではなく変数である場合、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:]]##}}
1
XDR

$(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)_フラグを使用して、一致しない要素を削除します)。

3
guest