それで、zsh
を使い始めました。私は大丈夫です。それは非常にクールで洗練されているように見え、現在の作業ディレクトリと実際のコマンドラインが別の行にあるという事実は素晴らしいですが、同時に、zsh
はbash
よりも少し遅くなる可能性があることに気付きました(特にテキストを印刷する場合)画面に。
私が一番気に入ったのは、zsh
が.bashrc
で定義したすべての関数と「下位互換性」があるという事実でした。
しかし、一つの不満。機能はすべて完璧に動作しますが、エクスポートシステムがどのように機能するのかわかりません。
これらの.bashrc
関数の一部をエクスポートして、export -f
を使用して、スクリプトや外部プログラムなどの他の場所で使用できるようにしました。
Zshでは、エクスポートについてさえ話されていないようです。自動読み込みですか?これら2つは同じですか?それを理解するのに非常に苦労しています。
関数を含む環境変数はbashハックです。 Zshには同様のものはありません。数行のコードで同様のことができます。環境変数には文字列が含まれます。 Shellshock が発見される前の古いバージョンのbashは、名前が関数の名前であり、値が() {
の後に関数のコードが続き、}
。次のコードを使用して、このエンコーディングで変数をインポートし、bashのような設定でそれらを実行することができます。 zshがすべてのbash機能をエミュレートできるわけではないことに注意してください。できるのは少し近づくことです(たとえば、$foo
で値を分割してワイルドカードを展開し、配列を0ベースにする)。
bash_function_preamble='
emulate -LR ksh
'
for name in ${(k)parameters}; do
[[ "-$parameters[name]-" = *-export-* ]] || continue
[[ ${(P)name} = '() {'*'}' ]] || continue
((! $+builtins[$name])) || continue
functions[$name]=$bash_function_preamble${${${(P)name}#"() {"}%"}"}
done
( StéphaneChazelas 、Shellshockの最初の発見者、と指摘したように、この回答の以前のバージョンは、関数定義が不正な形式である場合、この時点で任意のコードを実行する可能性がありました。このバージョンはそうではありませんが、もちろんコマンドを実行するとすぐに、環境からインポートされた関数になる可能性があります。)
シェルショック後のバージョンのbashエンコード環境では、無効な変数名を使用して関数をエンコードします(例:BASH_FUNC_myfunc%%
)。 zshはこのような変数名を環境から抽出するためのインターフェースを提供していないため、これはそれらを確実に解析することを困難にします。
これはお勧めしません。スクリプトでエクスポートされた関数に依存することは悪い考えです。スクリプトで目に見えない依存関係が作成されます。機能のない環境でスクリプトを実行した場合(別のマシン、cronジョブで、シェルの初期化ファイルを変更した後など)、スクリプトは動作しなくなります。代わりに、すべての関数を1つ以上の個別のファイル(~/lib/Shell/foo.sh
など)に保存し、使用する関数(. ~/lib/Shell/foo.sh
)をインポートしてスクリプトを開始します。このように、foo.sh
を変更すると、それに依存しているスクリプトを簡単に検索できます。スクリプトをコピーすると、必要な補助ファイルを簡単に見つけることができます。
Zsh(およびその前のksh)は、関数が使用されるスクリプトに関数を自動的にロードする方法を提供することにより、これをより便利にします。制約は、ファイルごとに1つの関数しか配置できないことです。関数をオートロードとして宣言し、関数定義を名前が関数の名前であるファイルに入れます。このファイルを$fpath
(FPATH
環境変数で設定できる)にリストされているディレクトリに配置します。スクリプトで、オートロードされた関数をautoload -U foo
で宣言します。
さらに、zshはスクリプトをコンパイルして、解析時間を節約できます。スクリプトをコンパイルするには、 zcompile
を呼び出します。これにより、.zwc
拡張子を持つファイルが作成されます。このファイルが存在する場合、autoload
はソースコードの代わりにコンパイルされたファイルをロードします。 zrecompile
function を使用して、ディレクトリ内のすべての関数定義を(再)コンパイルできます。
関数宣言を。zshenvに入れると、関数はスクリプトから簡単に使用できます。