質問しました

質問しました

いくつかのコードを書いている間、私は次の行を見つけました:

$ TZ="America/Los_Angeles"       date; echo "$TZ"
Thu Dec 24 14:39:15 PST 2015

「ロサンゼルス」の実際の時間を正しく提供し、TZ変数値を保持しません。すべてが期待どおりに動作します。

ただし、この行はいくつかの書式を拡張し、本質的に同じことを実行してTZ値を維持するために使用します。

TZ="America/Los_Angeles" eval  date; echo "$TZ"
Thu Dec 24 14:41:34 PST 2015
America/Los_Angeles

多くのテストの後、これは特定のシェルでのみ発生することがわかりました。 dash、kshでは発生しますが、bashまたはzshでは発生しません。

質問しました

問題は次のとおりです。

  • 現在のシェルにTZ値が保持されているのはなぜですか?
  • (可能な場合)これをどのように回避または制御できますか?

追加の。

次の2行を使用して、複数のシェルでテストを実行しました。

myTZ="America/Los_Angeles"
unset TZ; { TZ="$myTZ"      date; } >/dev/null; echo -n "  direct $TZ"
unset TZ; { TZ="$myTZ" eval date; } >/dev/null; echo    "  evaled $TZ"

結果:

/bin/ash        :   direct   evaled America/Los_Angeles
/bin/dash       :   direct   evaled America/Los_Angeles
/bin/sh         :   direct   evaled America/Los_Angeles
/bin/bash       :   direct   evaled
/bin/ksh93      :   direct   evaled America/Los_Angeles
/bin/lksh       :   direct   evaled America/Los_Angeles
/bin/mksh       :   direct   evaled America/Los_Angeles
/bin/zsh        :   direct   evaled
/bin/zsh4       :   direct   evaled 

TZ値は、bashとzshを除くすべてのシェルで実行されているシェルに影響します。

ベストアンサー1

あなたが見つけたように、これは標準的な動作です。しかし、それも意味があります。

コマンドラインに定義を追加すると、他のコマンドが他の環境変数の値を保持するのと同じ理由で、値はシェル環境に保持されます。環境で変数を設定することです。

これ特殊組み込み機能通常、すべてのシェルの最も重要な種類 -eval基本的に、シェルパーサーのアクセス可能な名前、setシェルオプション、およびシェル引数の追跡と設定、return//ループ制御フロートリガ、break信号処理、ファイルの開閉。これは、包装紙をほとんどまたはまったく使用せずに入手できる基本的なユーティリティです。continuetrapexec

ほとんどのコマンドを実行するには、一部の階層化環境が必要です。サブシェル環境(必ずしも別のプロセスである必要はありません)- 特別な組み込み関数を呼び出すと不明です。したがって、これらのコマンドのいずれかに環境を設定すると、シェルの環境も設定されます。基本的にはシェルを表すからです。

しかし、このように環境を保存するコマンドはこれだけではありません。関数も同じことを行います。エラーは特殊な組み込みコマンドに対して異なる動作をします。cat <doesntexisttryの後に試したり、コマンドが文句を言ったり、POSIXシェルを終了したりするexec <doesntexistときも同様です。コマンドラインの拡張エラーも同様です。彼ら: <doesntexistcatexec:メインループ、基本的に。

これらのコマンドは持つ環境を維持するために、一部のシェルは内部を他のシェルよりもしっかりと包み込み、コア機能をあまり露出させず、プログラマとインタフェースの間にバッファを追加します。これらの同じシェルは他のシェルよりも遅くなる可能性があります。もちろん、規制を遵守するには、非標準的な調整がたくさん必要です。とにかくこれではありません。悪いもの:

fn(){ bad_command || return=$some_value return; }

それはシンプル。それ以外の場合は、bad_commandさまざまな設定をせずに戻り値を簡単に維持できますか?追加環境ですが、まだ条件付きで作業を実行していますか?

arg=$1 shift; x=$y unset y

このものも動作します。所定の位置で交換する方が簡単です。

IFS=+  set -- "$IFS" x y z
x="$*" IFS=$1 shift
echo "${x#"$IFS"}" "$*"

+x+y+z x y z

...または...

expand(){
    PS4="$*" set -x "" "$PS4" 
    { $1; }  2>&1
    PS4=$2   set +x
}   2>/dev/null

x='echo kill my computer; $y'
y='haha! just kidding!' expand "${x##*[\`\(]*}"

...私が楽しんで使うもう一つは...

echo kill my computer; haha! just kidding!

おすすめ記事