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
シェルではパラメータ拡張分裂を避けるために引用は必要ありません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 が配列の場合、一致する配列要素が削除されます。(M)
一致しない要素を削除するには、このフラグを使用してください。