Bash で長さがゼロでない文字列をテストする: [ -n "$var" ] または [ "$var" ] 質問する

Bash で長さがゼロでない文字列をテストする: [ -n

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

おすすめ記事