Bash変数の初期化-必要に応じて、推奨、または定義してください。


9

メインコードの前、または実際の値を割り当てる前に関数内のローカル変数のいずれかで、スクリプト内のbash変数の値を初期化することのメリット/デメリットはありますか?

私はこのようなことをする必要がありますか?

init()
{
    name=""
    name=$1
}

init "Mark"

変数がガベージ値で初期化されて(初期化されていない場合)、変数の値に悪影響を与えるリスクはありますか?


2
どこでこのアイデアを得ましたか?

6
@DoritoStyleさて、Cなどの低レベル言語に慣れている場合、これは心配する必要がある完全に有効なものです。
クサラナンダ

@Kusalananda Cはそのコードに相当しませんname = ""; name = argv[1];か?そして、それは無意味ではありませんか?
ジョセフSible-Reinstateモニカ

1
@ JosephSible-ReinstateMonicaはい。あなたが投稿したCコードは無意味です。ただし、Cでは、シェルとは異なり、初期化されていない変数には、明確に定義された特定の値はありません。これは、Cなどの言語で変数を初期化することは、多くの状況で意味があることを意味します。シェルでこれを行う必要はありません。ご指摘のとおり、C 変数を初期化してすぐに別の値に設定しても意味がありません。
Kusalananda

回答:


22

空の文字列を変数に割り当て、すぐに別の変数文字列を変数に割り当てることには利点がありません。シェル変数に値を割り当てると、以前の値が完全に上書きされます。

私の知る限りでは、変数を空の文字列に明示的に初期化する必要があるという推奨はありません。実際、これを行うと、特定の状況下でエラーがマスクされる場合があります(で実行した場合に明らかになるエラー、set -u以下を参照)。

設定されていない変数は、スクリプトの開始以降使用されていないか、スクリプトでunsetコマンドを実行して明示的に設定解除されているため、値がありません。そのような変数の値は何もありません。として使用"$myvariable"すると""、と同等の結果が得られ、「ガベージデータ」を取得することはありません。

シェルオプションnounsetがまたはのいずれset -o nounsetset -uで設定されている場合、未設定の変数を参照すると、シェルでエラーが発生します(非インタラクティブシェルは終了します)。

$ set -u
$ echo "$myvariable"
/bin/sh: myvariable: parameter not set

または、中bash

$ set -u
$ echo "$myvariable"
bash: myvariable: unbound variable

変数の名前が既存の環境変数に対応する場合、シェル変数は環境によって初期化されます。

この方法で環境によって初期化される可能性のある変数を使用していると予想される場合(そしてそれが望ましくない場合)、スクリプトの主要部分の前に明示的に設定を解除できます。

unset myvariable    # unset so that it doesn't inherit a value from the environment

環境変数としても削除されます。または、初期値を無視して、割り当てで上書きするだけです(環境変数の値も変更されます)。

シェル変数で初期化されていないガベージに遭遇することは決してありません(述べられているように、そのガベージが同じ名前で環境変数にすでに存在していた場合を除きます)。


3
変数を空の値に設定してすぐにOPを文字どおりに設定する値はありませんが、unsetある種のループforまたはwhile計算された値に設定するためのループを実行する前に、空の値(またはting)を設定することには価値があります。条件が満たされていないためにループが実際に実行されない可能性がある場合の値。変数は、スクリプトが継承した環境で他の値に設定されている可能性があります。しかし、間違いなくすべてをaに入れmain()、変数をとして定義する方が良いでしょうlocal
モンティハーダー

を省略して:、パラメータ拡張演算子を使用して未設定の変数を検出することもできます。例${myvariable-defaultvalue}
Barmar

3

編集:おっと、どうやら宣言は初期化とは異なります。とにかくこれはここに置いておきますので、私のような初心者のプログラマーは私の間違いから学ぶことができます。


関数でローカル変数を宣言する利点は、コードを簡単にコピーできることです。

たとえば、次の関数があるとします。

foo(){
    local name
    name="$1"
    echo "$name"
}

スクリプトにしたい場合は、localステートメントを無視して他のすべてをコピーします。

#!/bin/bash
name="$1"
echo "$name"

宣言と割り当てが同じ行にある場合はlocal、スクリプトに変換する前に、パーツを手動で編集する必要があります。

foo(){
    local name="$1"
    echo "$name"
}

この例では大したことではありませんが、大きくて複雑な関数を扱っている場合は、さらに面倒になります。


1
問題は、宣言と初期化の組み合わせに関するものではありませんでした。実際の値を割り当てる前に、空の値で初期化するかどうかについてでした。
Barmar

@Barmarああ、「初期化」を調べたところです。「宣言」と同義だと思いました...
wjandrea
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.