bash 4.3では、手動動作と実際の動作の間に違いがあるようです。
unset string # just to be sure
declare string # $? is 0 afterwards
declare -p string # fails, 'string: not found'
printf %b "${string-unset}" "\n" # consequently, yields unset
組み込み宣言/組版マニュアルセクションには、宣言時に割り当てが必要な宣言はありません。代わりに、このdeclare [...] [...] name[=value]
記号はこれが正当でなければならないことを意味します。
私は何を見逃していますか?変数を「設定」することが何を意味するのか?少なくとも「設定解除」という用語を使用するマニュアルの「パラメータ拡張」セクションを誤って読みましたか?それとも、これは単なるバージョン固有の奇妙な点ですか?
答え1
bash バージョン 3.2 以下の場合、順序は次のとおりです。
$ declare string; declare -p string
printdeclare -- string=""
は、変数が空の文字列に設定されていることを示します。
バージョン4.1、4.2、4.3では、この変数は何も設定されておらず、実際にエラーが発生します。
$ declare string; declare -p string
bash: declare: string: not found
Bash 4.4で修正されました。
$ declare string; declare -p string
declare -- string
これは、文字列が宣言されたが値が割り当てられていないことを意味します(nullでもない)。
答え2
実際、パラメータ/変数の意味の仮定は次のとおりです。未設定OPの内容が正しくありません。
man bash
変数を特殊タイプのパラメータとして定義します。したがって、変数に関する情報は、一般パラメータのみを扱う部分に配置されることがあります。
変数を表す一般用語
変数の特性と状態を記述する用語変数に関するウィキペディア記事。
- 報告状況:メモリが予約されており、名前が存在します。
- 初期化状態:1.に追加の値を割り当てます。 (宣言直後)
- 初期化されていない状態:値が未定義、初期値が設定されていません(宣言のみ発生)
- 無効value: 初期化されていない変数を表すために一部のプログラミング言語で返される予約済み/特殊値
Bash マニュアルの変数関連項目
- 状態設定:「パラメータに値が割り当てられている場合、パラメータは設定されています。」
- 状態が設定されていません、あいまいさは、一般用語に従って「初期化されていない状態」の変数だけでなく、存在しない変数またはもはや存在しない変数に適用されるようです。 [パラメータ拡張段落]
- 空/空の文字列- NULL: "パラメータに値が割り当てられている場合、パラメータは設定されます。空の文字列は有効な値です。"
- 内蔵設定されていません- 変数を「オフにする」コマンド(例
unset string
:「名前ごとに変数を削除します...」[SHELL BUILTIN COMMANDSセクション、 'unset'段落]) - 組み込み宣言- 例
declare -p string
: "-p オプションは各名前の属性と値を表示します。
元の質問を変えて答えてください。
質問は、次のようにより正確に表現する必要があります。初期化されていないbash変数と存在しない変数を区別する方法は?」
これに対する答えは次のとおりです。
これについて混同しないでください
unset
組み込み存在する変数を削除し、その中の変数を削除します。状態が設定されていませんBash用語で宣言されていないか、値なしで宣言されました。declare
組み込みコマンドは、値なしで宣言された変数に対してbash 4.3とbash 4.4で一貫して動作しません。$ # bash 4.3 $ unset string; declare string; declare -p string; echo $? bash: declare: string: not found 1 $ # bash 4.4 $ unset string; declare string; declare -p string; echo $? declare -- string 0
したがって、使用中の単一変数名をテストするこの方法は普遍的ではありませんが、最新のbashバージョンでは機能しているようです。
残念ながら、パラメータ拡張は存在しない変数と初期化されていない変数を区別するのに役立ちません。どちらの場合も同じ変数に含まれているからです。状態が設定されていません:
$ declare string; echo ${string-UNSET} # `string` exists, empty UNSET $ unset string; echo ${string-UNSET} # `string` does not exist UNSET
残念ながら、条件演算子は
-v
VARNAMEが存在するかどうかを示さず、「シェル変数VARNAMEが設定されている(値が割り当てられているかどうか)」をテストする[マニュアルセクションCONDITIONAL EXPRESSIONS]には役立ちません。$ unset string; ! [ -v string ] && echo "unused" unused $ declare string; ! [ -v string ] && echo "unused" unused
関連トピック
ディスカッションでは、パラメータ/変数の状態と値に関する用語の混乱とbashの詳細に焦点を当てます。