【and, or, not】bashのif文で条件式を使う方法を解説

Bash

bashのif文でand, or, notなどの条件式を使うことで、複雑な条件分岐を実現できます。本記事では、これらの条件式の使い方と実践的な例を解説します。

if文

bashにおけるif文は、条件を評価してその結果に基づいて処理を分岐させます。条件が真と評価された場合の処理をthenキーワードの後に記述し、条件が偽の場合の処理をelseで指定することも可能です。

if文についての詳しい説明はこちらを参照ください。

条件式

bashでは主に以下の2つの方法で条件式を記述できます。

testコマンド(または[コマンド)

testコマンドはシェルに組み込まれた条件評価コマンドで、ファイルの存在や文字列の比較などを行います。

# 基本構文
if test 条件式; then
    # 条件が真の場合の処理
fi

# または [ ] を使用した構文
if [ 条件式 ]; then
    # 条件が真の場合の処理
fi

# 数値比較の例
if [ "$num" -eq 5 ]; then
    echo "数値は5です"
    # 出力: 数値は5です
fi

# 文字列比較の例
if [ "$str" = "test" ]; then
    echo "文字列はtestです"
    # 出力: 文字列はtestです
fi

[[(拡張テスト構文)

[[はbashの拡張機能で、testコマンドの機能に加えて、パターンマッチングなどの高度な操作が可能です。

# 基本構文
if [[ 条件式 ]]; then
    # 条件が真の場合の処理
fi

# 正規表現マッチングの例
if [[ "$string" =~ ^[0-9]+$ ]]; then
    echo "文字列は数字のみで構成されています"
    # 出力: 文字列は数字のみで構成されています
fi

# ワイルドカードの例
if [[ "$filename" == *.txt ]]; then
    echo "テキストファイルです"
    # 出力: テキストファイルです
fi

「-f」は「ファイルが存在し、通常ファイルである」ことをテストするための演算子です。

testコマンドと拡張テスト構文[[の違い

testコマンドと拡張テスト構文[[には重要な違いがあります。適切な構文を選ぶことでスクリプトの安全性と機能性が向上します。

1. 構文と互換性

testコマンドはPOSIX標準に準拠しており、ほぼすべてのシェルで動作します。一方、[[構文はbash、ksh、zshなど特定のシェルでのみ使用可能です。

# testコマンドの例(広い互換性)
if test -f "$file"; then
    echo "ファイルが存在します"
    # 出力: ファイルが存在します
fi

# または [ ] を使用した同等の構文
if [ -f "$file" ]; then
    echo "ファイルが存在します"
    # 出力: ファイルが存在します
fi

# [[ ]] 構文(bash、ksh、zshなど特定のシェルのみ)
if [[ -f "$file" ]]; then
    echo "ファイルが存在します"
    # 出力: ファイルが存在します
fi

2. 単語分割と変数展開

testコマンドでは変数展開時に単語分割が発生するため、空白を含む変数は必ず引用符で囲む必要があります。[[構文では単語分割が自動的に抑制されます。

# testコマンドでの問題例(引用符なし)
filename="my file.txt"
if [ -f $filename ]; then  # エラー: 単語分割により「my」と「file.txt」が別々の引数になる
    echo "ファイルが存在します"
    # 出力: エラーが発生
fi

# testコマンドでの正しい例(引用符あり)
if [ -f "$filename" ]; then  # 正しい: 「my file.txt」が一つの引数として扱われる
    echo "ファイルが存在します"
    # 出力: ファイルが存在します
fi

# [[ ]] 構文では単語分割が発生しない
if [[ -f $filename ]]; then  # 正しく動作する(ただし引用符を使用するのが良い習慣)
    echo "ファイルが存在します"
    # 出力: ファイルが存在します
fi

3. パターンマッチング

testコマンドは正規表現をサポートしていませんが、[[構文は=~演算子による正規表現とワイルドカードをサポートしています。

# testコマンドでのパターンマッチング(限定的)
if [ "$filename" = "*.txt" ]; then  # 文字通り「*.txt」という名前と比較
    echo "テキストファイルです"
    # 出力: テキストファイルです(ファイル名が実際に"*.txt"の場合のみ)
fi

# [[ ]] 構文での正規表現マッチング
if [[ "$string" =~ ^[0-9]+$ ]]; then  # 数字のみで構成された文字列かチェック
    echo "文字列は数字のみで構成されています"
    # 出力: 文字列は数字のみで構成されています
fi

# [[ ]] 構文でのワイルドカードマッチング
if [[ "$filename" == *.txt ]]; then  # .txtで終わるファイル名かチェック
    echo "テキストファイルです"
    # 出力: テキストファイルです
fi

4. 論理演算子

testコマンドでは-a(AND)や-o(OR)を使用しますが、これらは非推奨です。[[構文では&&(AND)や||(OR)を直接使用できます。

# testコマンドでの論理演算(非推奨の方法)
if [ -f "$file" -a -r "$file" ]; then  # 非推奨: -a演算子の使用
    echo "ファイルが存在し、読み取り可能です"
    # 出力: ファイルが存在し、読み取り可能です
fi

# testコマンドでの推奨される方法
if [ -f "$file" ] && [ -r "$file" ]; then  # 推奨: 別々のテストを&&で連結
    echo "ファイルが存在し、読み取り可能です"
    # 出力: ファイルが存在し、読み取り可能です
fi

# [[ ]] 構文での論理演算
if [[ -f "$file" && -r "$file" ]]; then  # シンプルで読みやすい
    echo "ファイルが存在し、読み取り可能です"
    # 出力: ファイルが存在し、読み取り可能です
fi

選択の指針

可能な限り[[構文を使用することで、より安全で機能的なスクリプトが書けます。ただし、他のシェルとの互換性が必要な場合はtestコマンドを使用してください。

and

bashでAND条件(複数の条件をすべて満たす)を表現するには、&&演算子を使用するのが最も一般的です。-a演算子も使えますが非推奨です。

  1. &&演算子を使用する – 左側の条件が真の場合のみ右側を評価し、両方が真の場合に全体が真になる
  2. [[ ]]内で&&を使用する – 拡張テスト構文内での論理AND
  3. -a演算子を使用する(非推奨)- 古い形式の論理AND演算子

以下は複数の条件をANDで結合する例です。

# 方法1: 複数のtest条件を && で連結
if [ -f "$file" ] && [ -r "$file" ]; then
    echo "ファイルが存在し、読み取り可能です"
    # 出力: ファイルが存在し、読み取り可能です
fi

# 方法2: [[ ]] 内で && を使用
if [[ -f "$file" && -r "$file" ]]; then
    echo "ファイルが存在し、読み取り可能です"
    # 出力: ファイルが存在し、読み取り可能です
fi

「-r」は「ファイルが読み取り可能である」ことをテストする演算子です。上記の例では、ファイルが存在し、かつ読み取り可能である場合にのみメッセージが表示されます。

注意: -a演算子は現在非推奨とされています。POSIX互換性の理由から、&&演算子や[[ ]]構文を使用することが推奨されています。将来のbashバージョンでは、-aは削除される可能性があります。

参考

or

bashでOR条件(いずれかの条件を満たす)を表現するには、||演算子を使用するのが最も一般的です。-o演算子も使えますが非推奨です。

  1. ||演算子を使用する – 左側の条件が偽の場合のみ右側を評価し、どちらか一方が真の場合に全体が真になる
  2. [[ ]]内で||を使用する – 拡張テスト構文内での論理OR
  3. -o演算子を使用する(非推奨)- 古い形式の論理OR演算子

以下は複数の条件をORで結合する例です。

# 方法1: 複数のtest条件を || で連結
if [ -f "$file" ] || [ -d "$file" ]; then
    echo "ファイルかディレクトリが存在します"
    # 出力: ファイルかディレクトリが存在します
fi

# 方法2: [[ ]] 内で || を使用
if [[ -f "$file" || -d "$file" ]]; then
    echo "ファイルかディレクトリが存在します"
    # 出力: ファイルかディレクトリが存在します
fi

「-d」は「ディレクトリが存在する」ことをテストする演算子です。上記の例では、ファイルまたはディレクトリが存在する場合にメッセージが表示されます。

注意: -o演算子も-aと同様に非推奨とされています。||演算子や[[ ]]構文を使用することが推奨されています。

not

条件を否定するには、!演算子を使用します。この演算子は条件の論理否定を行い、真を偽に、偽を真に変換します。

# ファイルが存在しない場合
if [ ! -f "$file" ]; then
    echo "ファイルが存在しません"
    # 出力: ファイルが存在しません
fi

# [[ ]]を使用する場合
if [[ ! -f "$file" ]]; then
    echo "ファイルが存在しません"
    # 出力: ファイルが存在しません
fi

「!」演算子は後に続く条件の結果を反転させます。上記の例では、ファイルが存在しない場合にメッセージが表示されます。

応用例

複数の条件を組み合わせることで、複雑な条件分岐を実現できます。以下は複数の条件を組み合わせた例です。

#!/bin/bash

file="example.txt"
backup="backup.txt"
permissions="644"

if [ ! -f "$file" ] || ([ -f "$file" ] && [ ! -r "$file" ]) && ([ ! -f "$backup" ] || [ -w "$backup" ]); then
    echo "処理実行: 条件一致"
    # 出力: 処理実行: 条件一致
fi

このスクリプトでは、以下の複雑な条件判定を行っています。

  1. メインファイルが存在しない(-fはファイルが存在するかを判定)、または
  2. メインファイルが存在するが読み取り権限がない(-rは読み取り権限があるかを判定)、かつ
  3. バックアップファイルが存在しないか、バックアップファイルが書き込み可能(-wは書き込み権限があるかを判定)

より読みやすく書くなら、[[構文を使用して以下のように書くこともできます。

#!/bin/bash

file="example.txt"
backup="backup.txt"

if [[ ! -f "$file" || (-f "$file" && ! -r "$file") ]] && [[ ! -f "$backup" || -w "$backup" ]]; then
    echo "処理実行: 条件一致"
    # 出力: 処理実行: 条件一致
fi

まとめ

bashのif文で条件式を使用する際のポイントは以下の通りです。

  1. 複数条件の「AND」には&&演算子を使用する(-aは非推奨)
  2. 複数条件の「OR」には||演算子を使用する(-oは非推奨)
  3. 条件の否定には!演算子を使用する
  4. 複雑な条件には[[ ]]拡張テスト構文を使用すると読みやすく、機能も豊富
  5. 変数は常に引用符で囲む(”$variable”)ことでスペースを含む値も正しく処理できる

これらの知識を活用して、堅牢で柔軟なbashスクリプトを作成できます。条件分岐を適切に使うことで、エラー処理や入力検証などの重要な機能を実装できます。

タイトルとURLをコピーしました