変数のグローバル文字が期待どおりに拡張されないzshの問題が見つかりました。次の例はこれをよりよく説明しています。
$ echo $0
-bash
$ echo $HOME/Downloads/zsh-test/*
/Users/bruce/Downloads/zsh-test/file1 /Users/bruce/Downloads/zsh-test/file2 /Users/bruce/Downloads/zsh-test/file3 /Users/bruce/Downloads/zsh-test/file4
$ file=*; echo $HOME/Downloads/zsh-test/$file
/Users/bruce/Downloads/zsh-test/file1 /Users/bruce/Downloads/zsh-test/file2 /Users/bruce/Downloads/zsh-test/file3 /Users/bruce/Downloads/zsh-test/file4
Macbook% echo $0
zsh
Macbook% echo $HOME/Downloads/zsh-test/*
/Users/bruce/Downloads/zsh-test/file1 /Users/bruce/Downloads/zsh-test/file2 /Users/bruce/Downloads/zsh-test/file3 /Users/bruce/Downloads/zsh-test/file4
Macbook% file=*; echo $HOME/Downloads/zsh-test/$file
/Users/bruce/Downloads/zsh-test/*
私は最後のコマンドがbashのように拡張されることを期待しました。私が間違っていることを知っていますか?
答え1
誰かがこれについて文句を言うのを見たのは、今回が初めてとなるでしょう(私たちは、人々が買収の拡張時にトークン化を行わないと文句を言うことをより頻繁に見ます)。
ほとんどの人は期待する
echo $file
変数の内容を印刷し、そのようなシェルが印刷されないと迷惑になります$file
(Bourneシェルから継承された動作、残念ながらkshによって変更されず、インタプリタのためにPOSIXによって指定されます)。これにより、多くのバグとセキュリティホールが発生します。これがこのシェルのすべての変数を引用する必要がある理由です。bash
sh
たとえば、次を参照してください。bash / POSIXシェルで変数を引用することを忘れてしまうセキュリティリスク
私はあなたが書くときにもこれを期待していることがわかりましecho $0
たecho "$0"
。
zsh
この問題は解決されました。デフォルトでは、パラメータ拡張中にワイルドカードやトークン化は行われません。以下を明示的に要求する必要があります。
echo $=file
: 単語分割の実行echo $~file
:ワイルドカードの実行echo $=~file
: 両方実行
globsubst
あるいは、Bourneのようなシェルと同じ動作を得るためにオプションを設定することもできます(shwordsplit
互換性が必要な場合は両方のオプションが有効になります)、他のシェル用に書かれたコードを解釈する必要がない限り、この方法はお勧めできません(この場合)を使用してローカルコンテキストで対応するコード解釈をシミュレートする方が合理的です。zsh
sh
sh
zsh
sh
emulate -L sh
file
ここに変数名を指定してください。
file=*
次のような場合に延長したい場合は、誤解を招く可能性があります。
filename_pattern=*
もっと理解できるでしょう。現在ディレクトリに隠されていないすべてのファイルの名前を変数に保存するには、次のようにします。
files=(*)
または:
files=(*(N))
現在のディレクトリに隠されていないファイルがない場合、割り当ては失敗しません。
つまり、大量に変数の割り当て。 ()は、一致がないとパターンが拡張されないというBourneシェルの他のバグ機能がないことを除いて、orまたはorと同じようにfile=(*)
機能します。bash
ksh93
mksh
yash
zsh
*
¹ この名前は、Unix シリーズシステムのファイルに完全に有効な名前です。ファイルを呼んでもrm -f -- $file
名前が保存されているファイルは削除されるという点で少しは慰めを受けます。$file
*