bashのexport -fと同等のzshは何ですか


24

だから私は使い始めましたzsh。大丈夫です。非常にクールと滑らかなようで、現在の作業ディレクトリと実際のコマンドラインは、異なるライン上にあるという事実はいいですが、同時に、私は気づいzshビットより遅いことができbash、にテキストを印刷する場合は特に画面。

私が一番気に入ったのは、でzsh定義したすべての関数と「下位互換性」があるという事実でした.bashrc

1つ不満です。これらの機能はすべて完全に機能しますが、エクスポートシステムがどのように機能するかはわかりません。

これらの.bashrc関数の一部をエクスポートして、スクリプトや外部プログラムなど、他の場所で使用できるようにしましたexport -f

zshでは、エクスポートについても言及されていないようです。自動ロードですか?これらの2つのことは同じですか?私はそれを理解するのに非常に苦労しています。


2
これは非常に古い質問ですが、「現在の作業ディレクトリと実際のコマンドラインが異なる行にある」とは、zshとはまったく関係がないと言いたいです。プロンプトの設定方法に依存します。それだけです。
4ae1e1 14年

回答:


11

関数を含む環境変数は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

(Shellshockの最初の発見者であるStéphaneChazelasが指摘したように、この回答の以前のバージョンは、関数定義の形式が正しくない場合、この時点で任意のコードを実行できます。このバージョンは、もちろん、コマンドを実行すると環境からインポートされた関数である可能性があります。)

シェルショック後バージョンの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関数を使用して、ディレクトリ内のすべての関数定義を(再)コンパイルできます。


1
あなたのコードがどのようにシェルショックの脆弱性をbash持っているかがおかしいです(変数の内容が関数定義にすぎずHTTP_HOSTまたはなどの変数名を処理することを確認しませんLC_X)。そうでなければ良い答え。
ステファンシャゼラス

@StéphaneChazelas環境からインポートされた関数を使用してコマンドを実行する場合、ほとんど失われています。しかし、任意のコードを実行しないようにインポートコードを更新しました。ただし、シェルショック後のbashはエクスポートされた関数を同じ方法でエンコードしないため、あまり有用ではありません。
ジル 'SO-悪であるのをやめる'

CVE-2014-6271に相当するものを修正しましたが、CSH-2014-6277 / 6278タイプの多くの脆弱性にさらされている可能性があります... zshパーサーを任意の変数のコードにさらしているためです。一部のコンテキストで攻撃者の制御下にある可能性のあるものを含みます(関数が呼び出されない場合でもコードzsh -c 'functions[f]=$VAR'解析さfれるため)。解決策は、それらのような予約されたテンプレートに続く名前の変数のみを考慮$BASH_FUNC_x%%することですが、あなたが言うように、それらzshをリストまたは取得するAPIはありません。perlたとえば、呼び出す必要があります。
ステファンシャゼラス

7

関数宣言を.zshenvに配置すると、関数はスクリプトから簡単に使用できます。


どうして私の答えに反対票を投じたのですか?説明してください。
ロール

まだ答えを待っていて、まだ働いています!
ロール

この答えを発見したばかりで、理想的なソリューションです。
AFH

私はそれを支持しませんでした。また、OPHのTBHは.bashrcからのものをエクスポートすることを求めていました。しかし、あなたのソリューションは同じ悪い考えの変種であり、すべてのスクリプトを入れて、.zshenv決して使用されない多くのコードを解析することにより、zshのすべての呼び出しを遅くします。さらに、エクスポートされた変数と同様に、エクスポートされた関数は子プロセスでのみ使用可能です。入れたもの.zshenvはすべてのzshで利用できます。
変態

最後に、に入れた個人コードに依存している場合.zshenv、すべてのスクリプトは完全に移植できなくなります。通常、スクリプトは互いに依存する可能性がありますが、それは問題ありません。一緒に配布します。彼らは特別な機能を有するに依存している場合でも.zshenv、誰もそれを使用したいんだろうか、彼らは特別で呼び出さなければならないZDOTDIR、あなた自身のを防ぐ.zshenv実行されているから。それは苦痛だろう。
変態
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.