Bashの "source"コマンドが関数から呼び出されたときに異なる動作をするのはなぜですか?

Bashの

次の利用可能なbarBashスクリプトが与えられたら...

echo :$#:"$@":

...そして次の実行可能なfooBashスクリプト:

echo -n source bar:
source bar
echo -n source bar foo:
source bar foo

function _import {
  source "$@"
}

echo -n _import bar:
_import bar
echo -n _import bar foo:
_import bar foo

Bashスクリプトを実行すると、次fooの出力が表示されます./foo

source bar::0::
source bar foo::1:foo:
_import bar::1:bar:
_import bar foo::1:foo:

私の質問は次のとおりです。

  1. source_import直接呼び出さずに関数からBashコマンドを呼び出すのはなぜ違うのですか?
  2. sourceBashコマンドの動作を正規化する方法は?

私はFedoraバージョン20でBashバージョン4.2.47(1)リリースを使用しています。

ベストアンサー1

問題は、sourceファイルが現在の環境で実行されるためです。では、bash位置引数が指定されていない限り変更されません。 ~からbash Bourne Shell 組み込み関数マニュアルページ:

。 (一定期間)

。ファイル名[パラメータ]

現在のシェルコンテキストのファイル名引数からコマンドを読み取り、実行します。ファイル名にスラッシュが含まれていない場合は、PATH変数を使用してファイル名を見つけます。 BashがPOSIXモードではない場合、$ PATHにファイル名がない場合は、現在のディレクトリが検索されます。引数が指定されると、filenameが実行されたときに位置引数になります。それ以外の場合、位置パラメータは変更されずにそのまま残ります。。戻り状態は、最後に実行されたコマンドの終了状態、またはコマンドが実行されていない場合は0です。ファイル名が見つからないか読み取れない場合、戻り状態はゼロではありません。この組み込み関数はソースコードと同じです。

POSIXの定義指すsourceinの同義語です):dotbash

シェルは現在の環境でファイルのコマンドを実行する必要があります。

また、 KornShell バージョンの dot は、位置引数に設定されたオプションの引数を取ることができることを説明します。

KornShellバージョンのdotは、位置パラメータに設定されたオプションのパラメータを使用します。これは、ドットスクリプトが関数と同じように機能することを可能にする有効な拡張です。

source barしたがって、内部関数を呼び出すときに_import位置引数を指定しないため、変更されません。これは_import関数の範囲と同じで、$@包含bar$#isです1(実行時_import bar)。

関数の範囲source bar外で呼び出すと、グローバル範囲(またはスクリプト)_importと同じです。fooこの場合は実行中なので、null と 0 の引数なしで./foo実行中です。foo$@$#

おすすめ記事