参照先のシェルスクリプトを実行せずに、あるシェルスクリプトから別のシェルスクリプトに変数をインポートする

参照先のシェルスクリプトを実行せずに、あるシェルスクリプトから別のシェルスクリプトに変数をインポートする

シェルスクリプトは2つあります。file1.shとfile2.shです。

ファイル1.sh

#!/usr/bin/env bash 
export var1="/data/share"
export var2='password'
echo "Hello"

ファイル2.sh

#!/usr/bin/env bash 
source file1.sh
echo $var1
echo $var2

file2.shを実行すると、次の出力が得られます。

Hello
/data/share
password

しかし、私が期待する出力は

/data/share
password

file2.sh で参照されると、file1.sh が実行されます。file1.sh を実行せずに、file2.sh で変数だけをインポートするにはどうすればよいですか?

答え1

bash スクリプトをソースしたときと実行したときとで異なる動作をさせたい場合 (言い換えると、スクリプト内に、その時点でコードを実行せずにアクセスしたいデータ項目がある場合) に使用するオプションが 3 つあります。コメントでは、ある程度それらについて触れました。

オプション1

調達時期を決定し、適切なタイミングで「調達」を終了する

スクリプトを2つのセクションに分割し、下位の2番目に到達する前にソースが取得されたらスクリプトを終了します。

定義 (関数 / 変数の割り当てなど) を含むスクリプトの上部セクションを作成しますが、直接コードを実行しません。

実行可能コード セクションが始まる直前に、スクリプトがソース化されていることを検出した場合にスクリプトを終了するロジックを配置します。次のコード セグメントはこれを実行します。


ファイル1.sh

#!/usr/bin/env bash
export var1="/data/share"
export var2='password'    
# --- End Definitions Section ---    
# check if we are being sourced by another script or shell
[[ "${#BASH_SOURCE[@]}" -gt "1" ]] && { return 0; }
# --- Begin Code Execution Section ---
echo "Hello"
echo $var1
echo $var2 


ファイル2.sh

#!/usr/bin/env bash 
source file1.sh
echo "$var1"
echo "$var2"


./file2.sh の実行出力

$ ./file2.sh 
/data/share
password

オプション2

これは通常、複雑な状況でのみ使用されますが、この特定の例ではやりすぎです。ソースするファイル内に関数を作成し、その関数内で呼び出し元が利用できるものを決定します。この場合、それは 2 つのエクスポートされた変数です。通常、連想配列がある場合にこのモードを使用しますが、それ以外の場合は渡すことがほぼ不可能です。また、tmp ファイルは呼び出し元によって削除される必要がありますが、この場合は削除しませんでした。


ファイル1.sh

#!/usr/bin/env bash 
export var1="/data/share"
export var2='password'
exportCfg() {
  tmpF=$(mktemp)
  declare -p var1 var2 > "$tmpF"
  echo "$tmpF"
}
if [ "$1" == "export" ]; then
  exportCfg;
  exit 0;
fi

echo "Hello"
echo $var1
echo $var2


ファイル2.sh

#!/usr/bin/env bash 
source $(./file1.sh export)


echo "$var1"
echo "$var2"

file2.shを実行した場合の出力は上記と同じです。

オプション3

私がこれを処理する一般的な最後の方法は、定義のみを保持し、ソースまたは直接実行時に実行されるコードを含まないライブラリ ファイルを使用することです。これは、コードを分割するだけです。私は、頻繁に使用される関数を含む bash の「ライブラリ」のグループを持っており、通常はプロジェクトごとに、構成データ (定数) を保存するための小さなソース可能なライブラリを設定します。そのデータに設定された配列が含まれている場合は、オプション 2 のバージョンも使用します。

答え2

変数がすべて同じ方法でエクスポートされている場合(エクスポート foo=bar)を使用すると、すべてを簡単に入手できます。バッシュプロセス置換機能:

source <(grep '^export .*=' file1.sh)

マニュアルページの抜粋:

プロセス置換 プロセス置換は、名前付きパイプ (FIFO) または開いているファイルの命名に /dev/fd 方式をサポートするシステムでサポートされます。<(リスト) または >(リスト) の形式をとります。プロセス list は、その入力または出力が FIFO または /dev/fd 内のファイルに接続された状態で実行されます。このファイルの名前は、展開の結果として現在のコマンドに引数として渡されます。>(リスト) 形式を使用する場合、ファイルに書き込むと、リストに入力が提供されます。<(リスト) 形式を使用する場合、引数として渡されたファイルは、リストの出力を取得するために読み取られる必要があります。

関連情報