空のシェル変数は、設定されていないシェル変数と同じではないことを覚えておくことが重要です。ただし、この区別は、[ test ]
. できることは、変数の展開の値を報告するtest
ことだけです - それを決定するのはパラメータの展開です。例えば:
var=value
echo "${var+I am \$var and I am set. I am currently ${var:+not} empty.}"
###OUTPUT###
I am $var and I am set. I am currently not empty.
また:
var=
echo "${var+I am \$var and I am set. I am currently ${var:+not} empty.}"
###OUTPUT###
I am $var and I am set. I am currently empty.
と[ test ]
:
{ _nstr() { echo 'I just evaluated a ""null string!' ; }
[ -z "$var" ] && _nstr
[ -z "" ] && _nstr
unset var
[ -z "$var" ] && _nstr
echo "${var+I am \$var and I am set. I am currently ${var:+not} empty.}"
}
###OUTPUT###
I just evaluated a ""null string!
I just evaluated a ""null string!
I just evaluated a ""null string!
うまくいけば、これで家に帰ります:
var=value
[ -z "${var+}" ] && _nstr
###OUTPUT###
I just evaluated a ""null string!
変数が空かどうかをポータブルに判断したい場合は、次のようにします。
${var:+false} [ -n "${var+1}" ] && echo \$var is set and null
このようなケースでは、シェルのパラメーター拡張を非常にうまく利用できると思います。場合によっては、一石で二羽の鳥を殺すことさえできます (最初の例を参照)。これは間違いなく移植可能でなければなりません。以下は、ここにあるオープン グループの POSIX シェル ガイドラインからの不完全なコピー/貼り付けです。
${parameter:-word}
- デフォルト値を使用します。パラメータが
unset
またはの場合null
、単語の展開が置換されます。それ以外の場合は、パラメーターの値が代入されます。
${parameter:=word}
- デフォルト値を割り当てます。parameter が
unset
またはの場合null
、word の展開が parameter に割り当てられます。いずれの場合も、パラメータの最終値が代入されます。この方法で割り当てることができるのは、位置パラメータや特殊パラメータではなく、変数のみです。
${parameter:?[word]}
- Null または未設定の場合はエラーを示します。パラメータが
unset
またはの場合null
、word の展開 (word が省略されている場合は設定されていないことを示すメッセージ) が標準エラーに書き込まれ、シェルはゼロ以外の終了ステータスで終了します。それ以外の場合は、パラメーターの値が代入されます。対話型シェルは終了する必要はありません。
${parameter:+word}
- 代替値を使用します。パラメータが
unset
またはnull
の場合は、null
置換されます。それ以外の場合は、word の展開が代用されます。
例:
${parameter:-word}
- この例では、がまたは
ls
の場合にのみ実行されます。(コマンド置換表記については、コマンド置換で説明しています。)
x
null
unset
$( ls)
${x:-$(ls)}
${parameter:=word}
% unset X
% echo ${X:=abc}
abc
編集:
アシッシュのワンライナーに気づいて、それを貼るだけでちょっと安っぽくなったので何とかしたい。したがって、ここに POSIX パラメータ展開の set-test ワンライナーがあります。
_JAIL="" ; echo "_JAIL is ${_JAIL:-unset or null.}"
まあ、それでも安いと思います。
EDIT2:
だから私はこれに気づきました:「...これらは私が今書いているスクリプトで機能しますが、Linuxよりもあいまいな環境であっても、合理的に互換性のあるshのようなシェルで機能する方法を知りたいですGNU ユーザーランドと bash または dash を備えた PC..."
申し訳ありませんが、私は個人的に専門家ではありませんが、かなり専門的に書かれた initramfs busybox スクリプトを掘り下げた後、渡された、または渡されなかった可能性のある引数から重要なシェル変数を定義する次の方法を最初に取り上げました。ほぼどこでも期待どおりに機能します。
ユーザーが変数を定義していない場合にのみ、変数をデフォルトの状態に設定するだけなので、実際に変数が定義されているかどうかを確認するための追加の作業は必要ありません。もちろん、他にもたくさんの用途がありますが、私はそれらを適切に使用できるほど頭がよくありません。
_VAR1=${1:-/default/path} ; _VAR2=${2:-"$_default_size"}
EDIT3:
phsは、質問で提起されたように、彼のメソッドが空の変数ではなく、空の変数をテストすることを指定したことは正しかった. このメソッドは、中央のコロンが使用されているかどうかに応じて同じことを行うことができます。これを実証するために、POSIX ガイドラインの下にある種のくだらない表をコピーしました。
{subs='substitute'; params='parameters'; assn='assign'; err='error'}
"$parameter" == |set && !null |set && null| !set
------------------ ------------- ----------- ----------
${parameter:-word} | subs params | subs word | subs word
------------------ ------------- ----------- ----------
${parameter-word} | subs params | subs null | subs word
------------------ ------------- ----------- ----------
${parameter:=word} | subs params | assn word | assn word
------------------ ------------- ----------- ----------
${parameter=word} | subs params | subs null | assn word
------------------ ------------- ----------- ----------
${parameter:?word} | subs params | err; exit | err; exit
------------------ ------------- ----------- ----------
${parameter?word} | subs params | subs null | err; exit
------------------ ------------- ----------- ----------
${parameter:+word} | subs word | subs null | subs null
------------------ ------------- ----------- ----------
${parameter+word} | subs word | subs word | subs null