簡単なBash変数テストは次のとおりです。
${varName:? "${varName} is not defined"}
これを関数に入れて再利用したい。どう?
フォロー失敗
#
# Test a variable exists
tvar(){
val=${1:? "${1} must be defined, preferably in $basedir"}
if [ -z ${val} ]
then
echo Zero length value
else
echo ${1} exists, value ${1}
fi
}
つまりテストが失敗した場合は、終了する必要があります。
lhunath'sのおかげで、私は何百回も見過ごしてきたBash man
ページの一部に導かれました。
サブストリング展開を実行しない場合、bashは が設定されていないかnullであるパラメーターをテストします。コロンを省略すると、設定されていないパラメータ のみがテストされます。
これにより、次の真理値表を作成するよう求められました。
|設定解除|セット|セットと|意味 | |でもnull | nullではない| ============ + ======= + ========== + ========== + ============================= $ {var-_} | T | F | T |非ヌルまたは未設定 ------------ + ------- + ---------- + -------- -+ ----------------------------- $ {var:-_} | T | T | T |常にtrue、substに使用します。 ------------ + ------- + ---------- + ------ ---- + ----------------------------- $ var | F | F | T | varが設定され、nullではない ------------ + ------- + ---------- + ------- --- + ----------------------------- $ {!var [@]} | F | T | T |変数が設定されています
この表は、最後の行の仕様を紹介しています。 Bash man
ページには、「名前が配列でない場合、名前が設定されている場合は0に展開され、それ以外の場合はnullに展開されます」と表示されます。この真理値表では、配列であっても同じように動作します。
あなたが探しているのは間接的です。
assertNotEmpty() {
: "${!1:? "$1 is empty, aborting."}"
}
このため、次のような場合、スクリプトはエラーメッセージを表示して中止されます。
$ foo=""
$ assertNotEmpty foo
bash: !1: foo is empty, aborting.
testfoo
が空であるかどうかだけを望む場合は、スクリプトを中止する代わりに、関数の代わりにこれを使用します。
[[ $foo ]]
例えば:
until read -p "What is your name? " name && [[ $name ]]; do
echo "You didn't enter your name. Please, try again." >&2
done
また、空と未設定パラメータの間に非常に重要な違いがあることに注意してください。これらの用語を混同しないように注意してください!空のパラメータは、設定されているが空の文字列に設定されているだけのパラメータです。未設定のパラメーターは、まったく存在しないパラメーターです。
前の例はすべてemptyパラメータをテストしています。 nsetパラメータをテストし、設定されたすべてのパラメータが空であるかどうかを検討する場合は、それらが空かどうかにかかわらず、次のように使用します。
[[ ! $foo && ${foo-_} ]]
次のような関数で使用します。
assertIsSet() {
[[ ! ${!1} && ${!1-_} ]] && {
echo "$1 is not set, aborting." >&2
exit 1
}
}
渡したパラメーター名が設定されていないパラメーターを示している場合にのみスクリプトを中止します。
$ ( foo="blah"; assertIsSet foo; echo "Still running." )
Still running.
$ ( foo=""; assertIsSet foo; echo "Still running." )
Still running.
$ ( unset foo; assertIsSet foo; echo "Still running." )
foo is not set, aborting.
[ -z ${parameter+Word} ]
を使用したい
man bash
の一部:
Parameter Expansion
...
In each of the cases below, Word is subject to tilde expansion, parameter expansion, command substitution, and
arithmetic expansion. When not performing substring expansion, bash tests for a parameter that is unset or null;
omitting the colon results in a test only for a parameter that is unset.
...
${parameter:+Word}
Use Alternate Value. If parameter is null or unset, nothing is substituted, otherwise the expansion of
Word is substituted.
...
言い換えると:
${parameter+Word}
Use Alternate Value. If parameter is unset, nothing is substituted, otherwise the expansion of
Word is substituted.
いくつかの例:
$ set | grep FOOBAR
$ if [ -z "${FOOBAR+something}" ]; then echo "it is unset"; fi
it is unset
$ declare FOOBAR
$ if [ -z "${FOOBAR+something}" ]; then echo "it is unset"; fi
$ FOOBAR=
$ if [ -z "${FOOBAR+something}" ]; then echo "it is unset"; fi
$ FOOBAR=1
$ if [ -z "${FOOBAR+something}" ]; then echo "it is unset"; fi
$ unset FOOBAR
$ if [ -z "${FOOBAR+something}" ]; then echo "it is unset"; fi
it is unset
$
この関数は、現在設定されている変数をテストします。変数は配列でもかまいません。 bashでは、0 == TRUE、1 == FALSEであることに注意してください。
function var.defined {
eval '[[ ${!'$1'[@]} ]]'
}
# Typical Usage of var.defined {}
declare you="Your Name Here" ref='you';
read -p "What's your name: " you;
if var.defined you; then # Simple demo using literal text
echo "BASH recognizes $you";
echo "BASH also knows a reference to $ref as ${!ref}, by indirection.";
fi
unset you # have just been killed by a master :D
if ! var.defined $ref; then # Standard demo using an expanded literal value
echo "BASH doesn't know $ref any longer";
fi
read -s -N 1 -p "Press any key to continue...";
echo "";
ここで明確にするために、関数はリテラルテキストをテストします。コマンドがbashで呼び出されるたびに、以下の場合を除いて、変数は一般に、基本的な値で「スワップアウト」または「置換」されます。
これがまさにあなたが望むものであるかどうかはわかりませんが、新しい+複雑なスクリプトを書くときに私が使用する便利なトリックは "set -o"を使用することです
set -o#設定されていない変数を検出すると、スクリプトを爆弾にします
例えば:
$ grep '$ 1' chex.sh
ケース「$ 1」
$ ./chex.sh
./chex.sh:111行目:$ 1:バインドされていない変数
$ ./chex.sh foo
正しくない/オプションが渡されていません。終了します
私はあなたが何が必要かを正確に理解していません。これにもかかわらず私はあなたに返信しようとしています。
つまりテストが失敗した場合は、終了する必要があります。
コード:
${varName:? "${varName} is not defined"}
「varName」という名前の変数がない場合、ゼロ以外の終了コードを返します。最後のコマンドの終了コードは$?
に保存されます。
コードについて:
val=${1:? "${1} must be defined, preferably in $basedir"}
多分それはあなたが必要としていることをしていません。 $1
が定義されていない場合、"${1}"
は何も置換されません。おそらく、置換せずに文字どおり${1}
を書く単一引用符を使用したいでしょう。
val=${1:? '${1} must be defined, preferably in $basedir'
if set | grep -q '^VARIABLE='
then
echo VARIABLE is set
fi