私の問題は、スクリプトのコーディングを開始したときに、いくつかの変数スコープの問題に遭遇し、ほとんどすべての変数をエクスポートするという悪い習慣が生まれたことです。
コードがかなり大きくなったので、コードを整理しようかと考えていました。その一環として、無駄なエクスポートをいくつか削除しています。残念ながら、変数のスコープに関する私の知識が完全かどうかはわかりません。この件について数ページ読んだ後でも。
私が知っていること(そして正しいことを願う):
1-変数をエクスポートすると、その内容がサブシェル プロセスで使用できるようになります。
export myvar="content"
2 - このように括弧で囲まれた部分は、エクスポートの削除によって影響を受けます (私の理解では、これがサブシェルを宣言/使用する唯一の方法です)。
$(grep "content" <<< $myvar)
3-スコープを設定せずに宣言された変数はグローバルです。
myvar="content"
4-ローカル変数を宣言しないので、関数内で問題が発生する心配はありません。
local myvar="i don't use this"
質問:
1- 私のコードが明らかに初心者っぽさを醸し出していないのに、無駄なエクスポートを削除する作業を進めることに意味はあるでしょうか?
2- 続行する場合、影響を受けてコードが壊れる可能性がある他の点に注意する必要がありますか? または、私の知識に間違っている/不完全な点はありますか?
3- 適切に記述された(そして完全な)変数スコープリファレンスをご存知の場合は、リンクを共有してください。
答え1
export
2 回評価しない限り、エクスポートされた変数にまったく影響を与えることなく、すべてのエクスポートを削除できます。2 回評価するとは、次のことを意味します。
var1=var2
export "${var1}=var3"
echo "$var2"
var3
代わりに以下を使用します:
set -a
...スクリプトの先頭で。その後に定義されるすべての変数は自動的に設定されますexported
。これには、以前に編集しなかった変数も含まれます。または、スクリプトの一部のみに設定し、後で設定を解除することexport
もできます。これは関数としても機能します。set -a
set +a
ただし、サブシェルは変数値を自動的に継承するため、次のようになります。
var1=value
( echo "$(echo "$var1")" )
value
export
その場合は違いはありません。
しかし、スクリプトが別のスクリプトを呼び出したり、export
ed した値を解釈する他の実行可能ファイルを呼び出したりして、それらの値の使用を停止するexport
と、それらの値は環境で使用できなくなります。次の例では、対話型シェルのプロンプトの内容を定義するシェル変数を使用して、 ed 変数のバリエーションが子プロセスに$PS1
どのように影響するかを示します。export
export PS1="$(printf "this is another executable\n > ")"
echo exit | sh -i
###OUTPUT###
this is another executable
> exit
exit
しかし ...
PS1="$(printf "this is another executable\n > ")"
echo exit | sh -i
###OUTPUT###
sh-4.3$ exit
exit
しかし、プロセスを呼び出すときに環境変数を明示的に宣言すると...
PS1="$(printf "this is another executable\n > ")"
{
echo exit | PS1=$PS1 sh -i
echo exit | sh -i
}
###OUTPUT###
this is another executable
> exit
exit
sh-4.3$ exit
exit