変数のグローバル文字は bash では拡張されますが、zsh では拡張されません。

変数のグローバル文字は bash では拡張されますが、zsh では拡張されません。

変数のグローバル文字が期待どおりに拡張されない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によって指定されます)。これにより、多くのバグとセキュリティホールが発生します。これがこのシェルのすべての変数を引用する必要がある理由です。bashsh

たとえば、次を参照してください。bash / POSIXシェルで変数を引用することを忘れてしまうセキュリティリスク

私はあなたが書くときにもこれを期待していることがわかりましecho $0echo "$0"

zshこの問題は解決されました。デフォルトでは、パラメータ拡張中にワイルドカードやトークン化は行われません。以下を明示的に要求する必要があります。

  • echo $=file: 単語分割の実行
  • echo $~file:ワイルドカードの実行
  • echo $=~file: 両方実行

globsubstあるいは、Bourneのようなシェルと同じ動作を得るためにオプションを設定することもできます(shwordsplit互換性が必要な場合は両方のオプションが有効になります)、他のシェル用に書かれたコードを解釈する必要がない限り、この方法はお勧めできません(この場合)を使用してローカルコンテキストで対応するコード解釈をシミュレートする方が合理的です。zshshshzshshemulate -L sh

fileここに変数名を指定してください。

file=*

次のような場合に延長したい場合は、誤解を招く可能性があります。

filename_pattern=*

もっと理解できるでしょう。現在ディレクトリに隠されていないすべてのファイルの名前を変数に保存するには、次のようにします。

files=(*)

または:

files=(*(N))

現在のディレクトリに隠されていないファイルがない場合、割り当ては失敗しません。

つまり、大量に変数の割り当て。 ()は、一致がないとパターンが拡張されないというBourneシェルの他のバグ機能がないことを除いて、orまたはorと同じようにfile=(*)機能します。bashksh93mkshyashzsh


*¹ この名前は、Unix シリーズシステムのファイルに完全に有効な名前です。ファイルを呼んでもrm -f -- $file名前が保存されているファイルは削除されるという点で少しは慰めを受けます。$file*

関連情報