9

私の知る限り、bash 関数でローカル変数を作成するには 2 つの方法があります。サブシェルを作成するか、すべての変数をローカルとして宣言します。

例えば:

# using local
function foo
{
  local count
  for count in $(seq 10)
  do
    echo $count
  done
}

また

# using subshell
function foo
{
  (
    for count in $(seq 10)
    do
      echo $count
    done
  )
}

明らかに、サブシェルを使用するバージョンは、すべての変数をローカルに宣言することを気にする必要がないため、作成が簡単です ( getoptsなどのツールによって作成/エクスポートされた (環境) 変数は言うまでもありません)。しかし、サブシェルの作成にはオーバーヘッドがあると想像できます。

では、より良いアプローチは何ですか?長所/短所は何ですか?

4

2 に答える 2

9

サブシェルの作成には が含まれるfork()ため、ローカル変数と比較して確実にオーバーヘッドがあります。サブシェルは安価ですが (必要なときにコストを気にする必要はありません)、無料ではありません。

スクリプトが頻繁に使用され、パフォーマンスが非常に重要な場合 (そのため、何百人ものユーザーが同時にスクリプトを 1 日に何度も実行することになります)、サブシェルのパフォーマンス コストが心配になるかもしれません。OTOH、月に 1 回実行し、スクリプト全体の実行時間が 10 秒未満の場合、おそらくそうではないでしょう。

ただし、明快さという点では、明示的に変数を宣言する方がはるかに優れています。これにより、スクリプトが壊れるリスクが軽減されます。誰かがやって来て、「このサブシェルは明らかに必要ない」(そして実際には必要ない) と言うからです。 t; 関数からサブシェルを削除したい)。

Perl スクリプトの進化を見てください。それらは、必要に応じて変数が存在するようになる、自由に参加できるものとして始まりました。それらは徐々により厳密になり、すべての変数を事前に宣言するのが通常のスタイルになりました。ある程度、シェルは同様の道をたどってきましたが、Perl ほど厳密ではありません。Awk も興味深いケース スタディです。その関数は、関数への引数でない限りグローバル変数を使用します。これにより、関数は、ローカル変数を効果的に定義する 3 つのアクティブな引数 (たとえば) と 5 つの非アクティブな引数で記述されます。それは「機能する」とはいえ、少し風変わりです。

于 2011-01-07T15:41:27.370 に答える
1

ここで、すべての関数が常にすべての変数をローカルとして宣言していることを確認することは非常に困難です。

これは非常にエラーが発生しやすく、常にサブシェル関数を使用することを好みます。

f() (
 echo "we are a subshell"
)

ローカル変数を宣言する必要はありませんが、グローバル変数を変更する方法もありません。私の意見では、これは良いことです!

追加の結果として、そのような関数のリターン/終了コードを常にチェックし、それに応じて行動する必要があります! これは、サブシェル関数内からスクリプトを終了できないためです!

f() (
   echo "Trying to exit"
   exit 1
)

f
echo "Did not exit"

これはスクリプトを終了しません。このようにする必要があります:

f() (
   echo "Trying to exit"
   exit 1
)

f || exit $?
echo "Did not exit"

これで終了します

于 2016-06-02T11:10:03.500 に答える