Bashスクリプトにおける条件分岐とテスト演算子の実践ガイド

1. 文字列の比較と検証

Bashスクリプトにおいて、文字列の比較や空文字の判定を行うための演算子は以下の通りです。

演算子 説明 使用例
= 等しい [ "abc" = "abc" ] (真)
!= 等しくない [ "abc" != "def" ] (真)
> / < 文字列の大小比較(ASCII順)。[[ ]] 内ではエスケープ不要 [[ "b" > "a" ]] (真)
-z 文字列の長さが0(空文字)である場合に真 [ -z "$var" ]
-n 文字列の長さが0でない場合に真 [ -n "$var" ]

重要な注意点: -z-n を使用して変数の空判定を行う際は、必ず変数をダブルクォーテーションで囲んでください。囲まない場合、変数が空のときに構文エラーが発生します。

# 変数が空の場合の安全な判定
user_input=""

# ダブルクォーテーションを使用(推奨)
if [[ -z "$user_input" ]]; then
    echo "入力が空です。"
fi

# 二重角括弧 [[ ]] を使用する場合、クォーテーションは省略可能だが、明示的に書く癖が安全
if [[ -z $user_input ]]; then
    echo "入力が空です。"
fi

ユーザーからの入力を求め、値が入力されなかった場合にスクリプトを終了する例:

read -p "ユーザー名とパスワードを入力: " username password

if [[ -z "$username" || -z "$password" ]]; then
    echo "エラー: 必須項目が入力されていません。"
    exit 1
fi
echo "認証処理を開始します..."

2. ファイルとディレクトリのテスト

ファイルシステムの状態を確認するためのテスト演算子です。条件テストは直接メッセージを出力せず、終了ステータス($?)を返します。

テスト符 説明
-eファイルまたはディレクトリが存在する
-f通常のファイルとして存在する
-dディレクトリとして存在する
-r読み取り権限がある
-w書き込み権限がある
-x実行権限がある
-sファイルが存在し、かつサイズが0より大きい
-Lシンボリックリンクである

指定されたパスの属性を stat コマンドを用いて効率的に取得するスクリプト:

target_path="$1"

if [[ $# -eq 0 ]]; then
    echo "使用法: $0 <ファイルパス>"
    exit 1
fi

if [[ -e "$target_path" ]]; then
    echo "パス: $target_path は存在します。"
    
    if [[ -f "$target_path" ]]; then
        echo "タイプ: 通常ファイル"
    elif [[ -d "$target_path" ]]; then
        echo "タイプ: ディレクトリ"
    elif [[ -L "$target_path" ]]; then
        echo "タイプ: シンボリックリンク"
    fi

    # statコマンドを使用して詳細情報を取得
    if [[ -f "$target_path" || -L "$target_path" ]]; then
        stat -c "サイズ: %s bytes, 権限: %A, 所有者: %U:%G, 更新日時: %y" "$target_path"
    else
        stat -c "権限: %A, 所有者: %U:%G, 更新日時: %y" "$target_path"
    fi
else
    echo "エラー: $target_path は存在しません。"
fi

3. 論理演算子とブール演算子

複数の条件を組み合わせるための演算子です。使用する括弧によって記法が異なります。

演算子 説明 使用可能な構文
-a / &&論理積(AND)[ ] では -a[[ ]] では &&
-o / ||論理和(OR)[ ] では -o[[ ]] では ||
!論理否定(NOT)すべてのテスト構文で使用可能
# 伝統的な [ ] 構文でのAND条件
if [ -f "/etc/passwd" -a -r "/etc/passwd" ]; then
    echo "ファイルが存在し、読み取り可能です。"
fi

# 現代的な [[ ]] 構文でのOR条件
if [[ "$USER" == "root" || "$USER" == "admin" ]]; then
    echo "管理者権限を持つユーザーです。"
fi

# コマンドの終了ステータスを利用した論理演算
ping -c 1 8.8.8.8 > /dev/null 2>&1 && echo "ネットワークは正常です" || echo "ネットワーク接続エラー"

4. 正規表現によるマッチング

[[ ]] 構文内では =~ 演算子を使用して、正規表現によるパターンマッチングが行えます。

ユーザー入力が整数、浮動小数点数、または英数字文字列のいずれであるかを判定するスクリプト:

read -p "数値または文字列を入力してください: " user_input

if [[ "$user_input" =~ ^-?[0-9]+$ ]]; then
    echo "判定結果: 整数です。"
elif [[ "$user_input" =~ ^-?[0-9]+\.[0-9]+$ ]]; then
    echo "判定結果: 浮動小数点数です。"
elif [[ "$user_input" =~ ^[a-zA-Z0-9]+$ ]]; then
    echo "判定結果: 英数字の文字列です。"
else
    echo "判定結果: 未知の形式、または特殊文字が含まれています。"
fi

5. 条件分岐構文:ifとcase

複雑なロジックを実装するための if 文と、特定の値に基づく分岐に適した case 文の使い分けを解説します。

if文によるサービス状態のチェック

システムサービスの起動状態と自動起動設定を確認するスクリプト:

service_name="$1"

if [[ -z "$service_name" ]]; then
    echo "使用法: $0 <サービス名>"
    exit 1
fi

# 実行状態のチェック
if systemctl is-active --quiet "$service_name"; then
    echo "[$service_name] 状態: 実行中 (Active)"
else
    echo "[$service_name] 状態: 停止中 (Inactive)"
fi

# 自動起動設定のチェック
if systemctl is-enabled --quiet "$service_name"; then
    echo "[$service_name] 自動起動: 有効 (Enabled)"
else
    echo "[$service_name] 自動起動: 無効 (Disabled)"
fi

case文によるOSディストリビューションの判定

case 文は、変数の値が複数のパターンのいずれに一致するかを評価するのに最適です。以下の例では、/etc/os-release を読み込んでOSの種類を判定します。

if [[ -f /etc/os-release ]]; then
    # os-releaseファイルの値を環境変数として読み込む
    source /etc/os-release
    os_id="$ID"
    
    case "$os_id" in
        centos|rhel|fedora|rocky|alma|kylin)
            echo "検出されたOS: RedHat系 ($os_id)"
            echo "パッケージマネージャ: yum / dnf / rpm"
            ;;
        ubuntu|debian|linuxmint|pop)
            echo "検出されたOS: Debian系 ($os_id)"
            echo "パッケージマネージャ: apt / dpkg"
            ;;
        arch|manjaro|endeavouros)
            echo "検出されたOS: Arch系 ($os_id)"
            echo "パッケージマネージャ: pacman"
            ;;
        *)
            echo "検出されたOS: 未サポートまたは不明なディストリビューション ($os_id)"
            ;;
    esac
else
    echo "エラー: /etc/os-release が見つかりません。"
    exit 1
fi

タグ: bash ShellScript ConditionalStatements regex FileTesting

8月21日 06:11 投稿