Bashのif文の書き方: [とtestの違い

27, 2020-08-25

目次

Bashのif文の書き方

Bashではif文を使うことができます。
これは特定の条件の時に処理を分岐させたいときに使われる文です。

Bashのif文は↓のように使います。

i=1

if [ $i == 0 ]; then
    echo "zero"
elif [ $i == 1 ] && [ $i -lt 2 ]; then
    echo "one"
else
    echo "other"
fi

実行結果。

one

if文の構造

Bashのif文は↓のような構造になっています。
「判定」部分のコマンドの結果が0ならthen~fi内の「処理」を実行し、0以外なら処理を実行しません。

if 判定; then
    処理
fi

また、セミコロンを付けない場合は↓のように書くことが出来ます。

if 判定
then
    処理
fi

「判定」部分にはtestコマンドを渡します。

# 1が1ならtrue
if test 1 -eq 1; then
    echo "true"
fi

実行結果。

true

testコマンドの使い方

testはファイルまたは値を比較し、オプションの条件にマッチすれば0を、マッチしなければ0以外を終了値として返すコマンドです。
たとえば2つの値が等しいかチェックしたい時は-eqオプションを使います。

# 1と1は等しい(eq)?
test 1 -eq 1
echo $?
# 0

# 0と1は等しい(eq)?
test 0 -eq 1
echo $?
# 1

ほかにも↓のようなオプションがあります。

# 1と0は等しくない?
test 1 -ne 0
echo $?
# 0

# 2は1以上?
test 2 -ge 1
echo $?
# 0

# 2は1より上?
test 2 -gt 1
echo $?
# 0

# 1は2以下?
test 1 -le 2
echo $?
# 0

# 1は2より下?
test 1 -lt 2
echo $?
# 0

特に文字列の比較では==!=を使います。

test "abc" == "abc"
echo $?
# 0

test "abc" != "def"
echo $?
# 0

testには他にも様々なオプションがあります。
詳しくはman testでマニュアルを参照してください。

testの代わりに[を使う

testと同じような振る舞いをするコマンドに[があります。
このコマンドは末尾の]を無視します。
よって[を使うとif文を↓のように書けます。

if [ 1 -eq 1 ]; then
    echo "true"
fi

実行結果。

true

[testのエイリアスのように見えますが、別のコマンドです。Ubuntuなどでは/usr/bin/[にバイナリが置かれています。

結果を反転する

testの結果を反転するには!を使います。

test ! 1 -eq 1
echo $?

実行結果。

1

if文と[を使う場合は↓のように書くことが出来ます。

if [ ! 1 -eq 0 ]; then
    echo "!!!"
fi

実行結果。

!!!

elif

if文にはelifを繋げることが出来ます。
これは「1つ前のif文の結果が0(真)でなかったら実行するif文」と言えます。

if [ 0 -eq 1 ]; then
    echo "0 is 1"
elif [ 1 -eq 1 ]; then
    echo "1 is 1"
fi

実行結果。

1 is 1

elifは1つのif文に何個でも繋げることが出来ます。

if false; then
    echo "false 1"
elif false; then
    echo "false 2"
elif true; then
    echo "true"
fi

実行結果。

true

else

if文にはelseを繋げることが出来ます。
elseは1つのif文に1つまで付けることが出来ます。
elseは「if文の結果がどれも0(真)でなかったら実行する文」と言えます。

if false; then
    echo "false 1"
elif false; then
    echo "false 2"
else
    echo "else!"
fi

実行結果。

else!

if文とtrueとfalse

truefalseコマンドはそれぞれ終了値を0, 1で返すコマンドです。

true
echo $?
# 0

false
echo $?
# 1

これらのコマンドを使えばif文にtruefalseを指定することが出来ます。

if true; then
    echo "true!"
fi
# true!

if false; then
    echo "false!"
else
    echo "else!"
fi
# else!

if文と変数

test[コマンドには変数を渡すことも出来ます。

i=0

if [ $i -eq 0 ]; then
    echo $i
fi

実行結果。

0

AND

2つのコマンドの結果からANDの論理値を得たい場合は↓のように&&で繋げます。

i=2

if [ $i -ge 1 ] && [ $i -le 3 ]; then
    echo "1 <= $i <= 3"
fi

実行結果。

1 <= 2 <= 3

これは「変数iの値が1以上かつ3以下なら」というif文になります。

OR

2つのコマンドの結果からORの論理値を得たい場合は↓のように||で繋げます。

i=1

if [ $i -eq 0 ] || [ $i -eq 1 ]; then
    echo "0 or 1"
fi
0 or 1

これは「変数iの値が0または1なら」というif文になります。

使用例

if文の使用例です。

偶数ならnyan, 奇数ならwan

for文でカウント変数をカウントし、カウント変数が偶数ならnyan, 奇数ならwanを表示するサンプルです。

for ((i=0; i<4; i++)); do
    if [ $((i % 2)) -eq 0 ]; then
        echo "nyan"
    else
        echo "wan"
    fi
done

実行結果。

nyan
wan
nyan
wan

終了しますか? 続行しますか?

終了しますか?(y/n)」というプロンプトを表示し、yが入力されたらループを終了するサンプルです。

while true; do
    echo "終了しますか?(y/n)"
    read line

    if [ $line == "y" ]; then
        echo "終了します"
        break
    elif [ $line == "n" ]; then
        echo "続行します"
    else
        echo "不正な入力です"
    fi
done

実行結果。

終了しますか?(y/n)
n
続行します
終了しますか?(y/n)
a
不正な入力です
終了しますか?(y/n)
y
終了します

ファイルは存在する?

ファイルの存在確認はtest-eオプションを使います。
また、結果を反転させるには!を使います。

fname1="a.sh"
fname2="b.sh"

if [ -e $fname1 ]; then
    echo $fname1は存在します
fi

if [ ! -e $fname2 ]; then
    echo $fname2は存在しません
fi

実行結果。

a.shは存在します
b.shは存在しません

問題

Q1: if文に繋げられる文節を答えよ

  1. try

  2. elif

  3. else

Q2: testで文字列の比較に使えるオプションを答えよ

  1. ==

  2. -eq

  3. !=

Q3: testの終了値がnのときif文は真と評価する。nの値を答えよ

  1. 1

  2. 2

  3. 0


正解

Q1: 2, 3
Q2: 1, 3
Q3: 3