Bash スクリプトが 2 つの異なる方法で長さがゼロでない文字列をテストしているのを見たことがあります。ほとんどのスクリプトは、次の-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
ベストアンサー1
編集:[
これは、 (別名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
変数の長さがゼロでないかどうかを確認するには、次のいずれかを実行します。
- 変数を一重括弧で囲んで引用する(列2a)
-n
変数を一重括弧で囲んで引用符で囲みます(列4a )- 二重括弧を引用符付きまたは引用符なしで使用し、
-n
(列 1b - 4b)の有無にかかわらず使用します。
列 1a の「2」というラベルの行から始まる結果を見ると、 が変数の内容を[
条件式の一部であるかのように評価していることが分かります(結果は、説明列の「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