Bashスクリプトが2つの異なる方法で長さ0以外の文字列をテストするのを見てきました。ほとんどのスクリプトは-nオプションを使用します。
#!/bin/bash
# With the -n option
if [ -n "$var" ]; then
# Do something when var is non-zero length
fi
ただし、-nオプションは実際には必要ありません。
# Without the -n option
if [ "$var" ]; then
# Do something when var is non-zero length
fi
どちらが良い方法ですか?
同様に、長さゼロのテストのより良い方法は次のとおりです。
if [ -z "$var" ]; then
# Do something when var is zero-length
fi
または
if [ ! "$var" ]; then
# Do something when var is zero-length
fi
編集:これは、[
(別名test
)と[[
の違いを示す完全なバージョンです。
次の表は、変数が引用符で囲まれているかどうか、一重括弧または二重括弧を使用しているかどうか、および変数にスペースのみが含まれているかどうかが、-n/-z
の有無にかかわらずテストの使用が変数のチェックに適しているかどうかに影響することを示しています。
| 1a 2a 3a 4a 5a 6a | 1b 2b 3b 4b 5b 6b
| [ [" [-n [-n" [-z [-z" | [[ [[" [[-n [[-n" [[-z [[-z"
-----+------------------------------------+------------------------------------
unset| false false true false true true | false false false false true true
null | false false true false true true | false false false false true true
space| false true true true true false| true true true true false false
zero | true true true true false false| true true true true false false
digit| true true true true false false| true true true true false false
char | true true true true false false| true true true true false false
hyphn| true true true true false false| true true true true false false
two | -err- true -err- true -err- false| true true true true false false
part | -err- true -err- true -err- false| true true true true false false
Tstr | true true -err- true -err- false| true true true true false false
Fsym | false true -err- true -err- false| true true true true false false
T= | true true -err- true -err- false| true true true true false false
F= | false true -err- true -err- false| true true true true false false
T!= | true true -err- true -err- false| true true true true false false
F!= | false true -err- true -err- false| true true true true false false
Teq | true true -err- true -err- false| true true true true false false
Feq | false true -err- true -err- false| true true true true false false
Tne | true true -err- true -err- false| true true true true false false
Fne | false true -err- true -err- false| true true true true false false
変数の長さがゼロでないかどうかを知りたい場合は、次のいずれかを実行します。
-n
を使用して、変数を単一の括弧で囲みます(4a列)-n
の有無にかかわらず、二重括弧を使用します(列1b-4b)「2」というラベルの付いた行から始まる列1aで、[
が変数のcontentsを評価していることを示していることに注意してください。条件式(結果は、説明列の「T」または「F」によって暗示されるアサーションと一致します)。 [[
を使用すると(列1b)、変数の内容は文字列と見なされ、評価されません。
列3aおよび5aのエラーは、変数値にスペースが含まれ、変数が引用符で囲まれていないために発生します。この場合も、列3bおよび5bに示すように、[[
は変数の内容を文字列として評価します。
同様に、長さゼロの文字列のテストでは、列6a、5b、および6bが正しい方法を示しています。また、否定が反対の操作を使用するよりも明確な意図を示す場合、これらのテストのいずれも否定できることに注意してください。例:if ! [[ -n $var ]]
。
[
を使用している場合、予期しない結果が発生しないようにするための鍵は、変数を引用することです。 [[
を使用して、それは問題ではありません。
抑制されているエラーメッセージは、「単項演算子が期待される」または「二項演算子が期待される」です。
これは、上記の表を作成したスクリプトです。
#!/bin/bash
# by Dennis Williamson
# 2010-10-06, revised 2010-11-10
# for http://stackoverflow.com/q/3869072
# designed to fit an 80 character terminal
dw=5 # description column width
w=6 # table column width
t () { printf '%-*s' "$w" " true"; }
f () { [[ $? == 1 ]] && printf '%-*s' "$w" " false" || printf '%-*s' "$w" " -err-"; }
o=/dev/null
echo ' | 1a 2a 3a 4a 5a 6a | 1b 2b 3b 4b 5b 6b'
echo ' | [ [" [-n [-n" [-z [-z" | [[ [[" [[-n [[-n" [[-z [[-z"'
echo '-----+------------------------------------+------------------------------------'
while read -r d t
do
printf '%-*s|' "$dw" "$d"
case $d in
unset) unset t ;;
space) t=' ' ;;
esac
[ $t ] 2>$o && t || f
[ "$t" ] && t || f
[ -n $t ] 2>$o && t || f
[ -n "$t" ] && t || f
[ -z $t ] 2>$o && t || f
[ -z "$t" ] && t || f
echo -n "|"
[[ $t ]] && t || f
[[ "$t" ]] && t || f
[[ -n $t ]] && t || f
[[ -n "$t" ]] && t || f
[[ -z $t ]] && t || f
[[ -z "$t" ]] && t || f
echo
done <<'EOF'
unset
null
space
zero 0
digit 1
char c
hyphn -z
two a b
part a -a
Tstr -n a
Fsym -h .
T= 1 = 1
F= 1 = 2
T!= 1 != 2
F!= 1 != 1
Teq 1 -eq 1
Feq 1 -eq 2
Tne 1 -ne 2
Fne 1 -ne 1
EOF
Bashに関する限り、 より強力な[[
を使用することをお勧めします。
if [[ $var ]]; then # var is set and it is not empty
if [[ ! $var ]]; then # var is not set or it is set to an empty string
上記の2つの構成体は、見た目がきれいで読みやすいように見えます。ほとんどの場合、それらで十分です。
Word splitting および globbing の危険がないため、[[
内の変数展開を引用する必要がないことに注意してください。
shellcheck の[[ $var ]]
および[[ ! $var ]]
についての苦情を防ぐには、-n
オプションを使用できます。
「空の文字列に設定されている」と「設定されていない」を区別する必要があるまれなケースでは、これらを使用できます。
if [[ ${var+x} ]]; then # var is set but it could be empty
if [[ ! ${var+x} ]]; then # var is not set
if [[ ${var+x} && ! $var ]]; then # var is set and is empty
-v
テストも使用できます。
if [[ -v var ]]; then # var is set but it could be empty
if [[ ! -v var ]]; then # var is not set
if [[ -v var && ! $var ]]; then # var is set and is empty
if [[ -v var && -z $var ]]; then # var is set and is empty
このトピックに関連する記事はたくさんあります。以下にいくつかを示します。
ここにいくつかのテストがあります
文字列が空でない場合はtrue:
[ -n "$var" ]
[[ -n $var ]]
test -n "$var"
[ "$var" ]
[[ $var ]]
(( ${#var} ))
let ${#var}
test "$var"
文字列が空の場合はtrue:
[ -z "$var" ]
[[ -z $var ]]
test -z "$var"
! [ "$var" ]
! [[ $var ]]
! (( ${#var} ))
! let ${#var}
! test "$var"
正解は次のとおりです。
if [[ -n $var ]] ; then
blah
fi
変数の引用を正しく処理する[[...]]
の使用に注意してください。
case/esac
を使用してテストします
case "$var" in
"") echo "zero length";;
esac
空のenv変数を評価する別の、おそらくより透過的な方法は、使用することです...
if [ "x$ENV_VARIABLE" != "x" ] ; then
echo 'ENV_VARIABLE contains something'
fi