シェルスクリプトにおける Bash キーバリュー配列の活用

ShellBeginner
オンラインで実践に進む

はじめに

このチュートリアルでは、シェルスクリプトにおける Bash のキーバリュー配列(連想配列とも呼ばれます)の理解と利用方法を説明します。キーバリュー配列は、数値インデックスではなく、記述的なキーを使用してデータを格納および取得できる強力なデータ構造です。

このチュートリアルを終える頃には、Bash スクリプトでキーバリュー配列を作成、操作、使用できるようになり、データをより効果的に整理し、従来の数値配列では困難な問題を解決できるようになります。

最初の Bash キーバリュー配列の作成

Bash のキーバリュー配列(連想配列とも呼ばれます)を使用すると、Python の辞書や JavaScript のオブジェクトのように、特定のキーに値を関連付けることができます。これにより、項目が位置ではなく名前で識別される構造化データを格納するのに最適です。

基本的な構文

Bash でキーバリュー配列を操作するには、まず-Aオプションを使用して宣言する必要があります。

declare -A myarray

これにより、myarrayという名前の空のキーバリュー配列が作成されます。-Aフラグは、これが連想(キーバリュー)配列であることを Bash に具体的に指示します。

配列への要素の追加

さまざまな果物に関する情報を格納するキーバリュー配列を作成してみましょう。

  1. まだ開いていない場合は、WebIDE で新しいターミナルを開きます。
  2. WebIDE で「File > New File」をクリックして、新しいスクリプトファイルを作成します。
  3. ファイルを/home/labex/projectディレクトリにfruit_array.shとして保存します。
  4. ファイルに次のコードを追加します。
#!/bin/bash

## キーバリュー配列を宣言する
declare -A fruits

## 配列に要素を追加する
fruits["apple"]="red"
fruits["banana"]="yellow"
fruits["grape"]="purple"
fruits["orange"]="orange"

## 特定の要素を出力する
echo "The color of an apple is ${fruits["apple"]}"

## すべての値を出力する
echo "All fruit colors: ${fruits[@]}"

## すべてのキーを出力する
echo "All fruits: ${!fruits[@]}"
  1. ファイルを保存します(Ctrl+S または File > Save)。
  2. ターミナルで次のコマンドを使用して、スクリプトを実行可能にします。
chmod +x fruit_array.sh
  1. スクリプトを実行します。
./fruit_array.sh

次のような出力が表示されるはずです。

The color of an apple is red
All fruit colors: red yellow purple orange
All fruits: apple banana grape orange

出力の理解

  • ${fruits["apple"]}: この構文は、キー「apple」に関連付けられた値を取得します。
  • ${fruits[@]}: これは、配列内のすべての値を返します。
  • ${!fruits[@]}: 配列名の前の!記号は、配列内のすべてのキーを返します。

Bash のキーバリュー配列を使用すると、数値位置を覚える必要がなく、意味のある名前を使用してデータに直接アクセスできるため、スクリプトの可読性と保守性が向上します。

Bash キーバリュー配列の操作

キーバリュー配列の基本を理解したところで、それらを操作する方法を探ってみましょう。このステップでは、既存の値の変更、新しい要素の追加、要素の削除、およびキーの存在確認について学びます。

新しいスクリプトの作成

  1. /home/labex/projectディレクトリにarray_operations.shという名前の新しいファイルを作成します。
  2. ファイルに次のコードを追加します。
#!/bin/bash

## キーバリュー配列を宣言する
declare -A user_info

## 初期要素を追加する
user_info["name"]="John Doe"
user_info["email"]="john@example.com"
user_info["age"]="30"
user_info["city"]="New York"

## 初期配列の内容を表示する
echo "--- Initial user information ---"
for key in "${!user_info[@]}"; do
  echo "$key: ${user_info[$key]}"
done

## 既存の値を変更する
user_info["age"]="31"

## 新しいキーバリューペアを追加する
user_info["country"]="USA"

## キーが存在するかどうかを確認する
if [[ -v user_info["email"] ]]; then
  echo -e "\nEmail exists: ${user_info["email"]}"
else
  echo -e "\nEmail does not exist"
fi

## 要素を削除する
unset 'user_info[city]'

## 変更された配列を表示する
echo -e "\n--- Modified user information ---"
for key in "${!user_info[@]}"; do
  echo "$key: ${user_info[$key]}"
done

## 要素の数をカウントする
echo -e "\nNumber of elements: ${#user_info[@]}"
  1. ファイルを保存します(Ctrl+S または File > Save)。
  2. スクリプトを実行可能にします。
chmod +x array_operations.sh
  1. スクリプトを実行します。
./array_operations.sh

次のような出力が表示されるはずです。

--- Initial user information ---
name: John Doe
email: john@example.com
age: 30
city: New York

Email exists: john@example.com

--- Modified user information ---
name: John Doe
country: USA
email: john@example.com
age: 31

Number of elements: 4

主要な操作の説明

  • 値の変更: 既存のキーに新しい値を割り当てるだけです:user_info["age"]="31"
  • 新しい要素の追加: 初期割り当てと同じ構文を使用します:user_info["country"]="USA"
  • キーが存在するかどうかの確認: -vテスト演算子を使用します:[[ -v user_info["email"] ]]
  • 要素の削除: unsetコマンドを使用します:unset 'user_info[city]'
  • 要素のカウント: 要素の数を取得するには${#array[@]}を使用します
  • 要素の反復処理: すべてのキーを取得するには、${!array[@]}を使用した for ループを使用します

変更された出力では、cityキーバリューペアが削除され、新しいcountryキーバリューペアが追加されていることに注目してください。また、ageの値が 30 から 31 に更新されています。

これらの操作は、スクリプトで動的データを扱う際に不可欠であり、必要に応じて情報を更新できます。

実用的な構成マネージャーの作成

キーバリュー配列の作成と操作方法を理解したところで、実用的なものを作成してみましょう。このステップでは、設定ファイルを読み込み、キーバリュー配列に格納し、アクセスできるようにするシンプルな構成マネージャーを作成します。

ステップ 1:構成ファイルの作成

まず、いくつかのサンプル設定を含む構成ファイルを作成しましょう。

  1. /home/labex/projectディレクトリにapp_config.txtという名前の新しいファイルを作成します。
  2. ファイルに次の内容を追加します。
database_host=localhost
database_port=3306
database_user=admin
database_password=secret123
app_name=MyAwesomeApp
debug_mode=true
max_connections=100
  1. ファイルを保存します。

ステップ 2:構成マネージャースクリプトの作成

次に、この構成ファイルを読み込み、その内容をキーバリュー配列に格納するスクリプトを作成しましょう。

  1. /home/labex/projectディレクトリにconfig_manager.shという名前の新しいファイルを作成します。
  2. ファイルに次のコードを追加します。
#!/bin/bash

## 構成ファイルへのパスを定義する
CONFIG_FILE="/home/labex/project/app_config.txt"

## 構成用のキーバリュー配列を宣言する
declare -A config

## ファイルから構成を読み込む関数
load_config() {
  local file=$1

  ## ファイルが存在するかどうかを確認する
  if [[ ! -f "$file" ]]; then
    echo "Error: Configuration file '$file' not found."
    return 1
  fi

  ## ファイルを1行ずつ読み込む
  while IFS='=' read -r key value; do
    ## 空行とコメントをスキップする
    if [[ -z "$key" || "$key" == \#* ]]; then
      continue
    fi

    ## キーバリューペアを配列に格納する
    config["$key"]="$value"
  done < "$file"

  echo "Configuration loaded successfully from '$file'"
  return 0
}

## 構成値を取得する関数
get_config() {
  local key=$1
  local default=$2

  ## キーが存在するかどうかを確認する
  if [[ -v config["$key"] ]]; then
    echo "${config["$key"]}"
  else
    echo "$default"
  fi
}

## すべての構成を表示する関数
display_config() {
  echo "--- Configuration Settings ---"
  for key in "${!config[@]}"; do
    echo "$key = ${config[$key]}"
  done
}

## 構成を読み込む
load_config "$CONFIG_FILE"

## すべての構成設定を表示する
display_config

## 特定の構成値を取得する例
echo -e "\n--- Example Usage ---"
db_host=$(get_config "database_host" "127.0.0.1")
db_port=$(get_config "database_port" "5432")
db_user=$(get_config "database_user" "root")
db_pass=$(get_config "database_password" "")
app_name=$(get_config "app_name" "DefaultApp")
debug_mode=$(get_config "debug_mode" "false")

echo "Database connection: $db_user@$db_host:$db_port"
echo "Application name: $app_name"
echo "Debug mode: $debug_mode"

## 存在しない値を取得する例(デフォルトが使用されます)
timeout=$(get_config "connection_timeout" "30")
echo "Connection timeout: $timeout (default value used)"
  1. ファイルを保存します(Ctrl+S または File > Save)。
  2. スクリプトを実行可能にします。
chmod +x config_manager.sh
  1. スクリプトを実行します。
./config_manager.sh

次のような出力が表示されるはずです。

Configuration loaded successfully from '/home/labex/project/app_config.txt'
--- Configuration Settings ---
database_host = localhost
database_port = 3306
database_user = admin
database_password = secret123
app_name = MyAwesomeApp
debug_mode = true
max_connections = 100

--- Example Usage ---
Database connection: admin@localhost:3306
Application name: MyAwesomeApp
Debug mode: true
Connection timeout: 30 (default value used)

構成マネージャーの理解

作成したスクリプトは、いくつかの重要なことを行います。

  1. 構成ファイルからキーバリューペアを読み取ります。
  2. これらのペアをキーバリュー配列に格納します。
  3. 次の機能を提供します。
    • ファイルから構成を読み込む
    • デフォルトのフォールバックを使用して、特定の構成値を取得する
    • すべての構成設定を表示する

このパターンは、実際のアプリケーションで構成設定を管理するために一般的に使用されます。主な利点は次のとおりです。

  • 集中管理された構成: すべての設定が 1 か所にあります
  • デフォルト値: 設定がない場合、デフォルト値を使用できます
  • 容易なアクセス: 設定は名前でアクセスできます
  • 柔軟性: スクリプトを変更せずに構成を更新できます

この例は、キーバリュー配列をシェルスクリプトで実際の問題を解決するために使用できる方法を示しています。変更を構成ファイルに保存したり、設定を検証したりする機能を追加することで、これを拡張できます。

キーバリュー配列を使用したメニュー駆動型スクリプトの構築

この最終ステップでは、キーバリュー配列を使用してユーザーの選択を格納および処理する、実用的なメニュー駆動型スクリプトを作成します。この例は、キーバリュー配列を使用して、よりインタラクティブでユーザーフレンドリーなコマンドラインアプリケーションを作成する方法を示しています。

メニューシステムの作成

  1. /home/labex/projectディレクトリにmenu_system.shという名前の新しいファイルを作成します。
  2. ファイルに次のコードを追加します。
#!/bin/bash

## メニューオプション用のキーバリュー配列を宣言する
declare -A menu_options
menu_options["1"]="Display system information"
menu_options["2"]="Check disk usage"
menu_options["3"]="List running processes"
menu_options["4"]="View network connections"
menu_options["q"]="Quit"

## 実行するコマンド用のキーバリュー配列を宣言する
declare -A menu_commands
menu_commands["1"]="display_system_info"
menu_commands["2"]="check_disk_usage"
menu_commands["3"]="list_processes"
menu_commands["4"]="view_network"

## システム情報を表示する関数
display_system_info() {
  echo -e "\n--- System Information ---"
  echo "Hostname: $(hostname)"
  echo "Kernel version: $(uname -r)"
  echo "System uptime: $(uptime -p)"
  echo "CPU information: $(grep 'model name' /proc/cpuinfo | head -1 | cut -d ':' -f 2 | xargs)"
  echo "Total memory: $(free -h | grep Mem | awk '{print $2}')"
}

## ディスク使用量を確認する関数
check_disk_usage() {
  echo -e "\n--- Disk Usage ---"
  df -h | grep -v tmp
}

## 実行中のプロセスを一覧表示する関数
list_processes() {
  echo -e "\n--- Top 10 Processes by Memory Usage ---"
  ps aux --sort=-%mem | head -11
}

## ネットワーク接続を表示する関数
view_network() {
  echo -e "\n--- Active Network Connections ---"
  netstat -tuln | grep LISTEN
}

## メニューを表示する関数
display_menu() {
  echo -e "\n=== System Utility Menu ==="
  for key in 1 2 3 4 q; do
    echo "$key. ${menu_options[$key]}"
  done
  echo -e "\nPlease enter your choice:"
}

## メインループ
while true; do
  ## メニューを表示する
  display_menu

  ## ユーザーの選択を読み込む
  read -r choice

  ## 選択が有効かどうかを確認する
  if [[ -v menu_options["$choice"] ]]; then
    ## ユーザーが終了を選択した場合
    if [[ "$choice" == "q" ]]; then
      echo "Exiting. Goodbye!"
      exit 0
    fi

    ## 対応するコマンドを実行する
    if [[ -v menu_commands["$choice"] ]]; then
      ## 選択に関連付けられた関数を呼び出す
      ${menu_commands["$choice"]}
    fi
  else
    echo "Invalid option. Please try again."
  fi

  ## ユーザーが結果を読めるように一時停止する
  echo -e "\nPress Enter to continue..."
  read -r
done
  1. ファイルを保存します(Ctrl+S または File > Save)。
  2. スクリプトを実行可能にします。
chmod +x menu_system.sh
  1. スクリプトを実行します。
./menu_system.sh
  1. 対応する番号を入力して、さまざまなメニューオプションを試してから、メニューに戻るように促されたら Enter キーを押します。終了したら、qを入力してプログラムを終了します。

メニューシステムの理解

このスクリプトは、キーバリュー配列のいくつかの高度な使用法を示しています。

  1. メニューオプション: menu_options配列は、オプション番号を説明テキストにマッピングします
  2. コマンドマッピング: menu_commands配列は、オプション番号を関数名にマッピングします
  3. 動的実行: スクリプトは、1 つの配列の値を使用して、どの関数を呼び出すかを決定します

このメニューシステムでキーバリュー配列を使用する利点には、以下が含まれます。

  • 保守性: メニューオプションの追加または変更には、配列の更新のみが必要です
  • 可読性: コードは、どのコマンドがどのメニューオプションに対応しているかを明確に示しています
  • 柔軟性: 関数呼び出しを変更することなく、メニュー項目を簡単に並べ替えることができます

このパターンは、保守と拡張が容易なインタラクティブなコマンドラインツールを作成するのに役立ちます。

主要なポイント

このチュートリアル全体を通して、次のことを学びました。

  1. Bash でキーバリュー配列を作成および初期化する方法
  2. キーバリュー配列から要素にアクセス、変更、および削除する方法
  3. キーバリュー配列のキーと値を反復処理する方法
  4. 構成データを格納するためにキーバリュー配列を使用する方法
  5. キーバリュー配列を使用してインタラクティブなメニューシステムを作成する方法

これらのテクニックは、単純なデータストレージから複雑なインタラクティブアプリケーションまで、幅広いシェルスクリプトタスクに適用できます。

まとめ

このチュートリアルでは、Bash のキーバリュー配列の力と多用途性を探求しました。基本から始めて、キーバリュー配列の作成とアクセス方法を学び、要素の変更、追加、削除などのより高度な操作に進みました。

この知識を応用して、ファイルから設定を読み込む構成マネージャーや、キーバリュー配列を使用してインタラクティブなコマンドラインアプリケーションを作成する方法を示すメニュー駆動型ユーティリティスクリプトなど、実用的な例を作成しました。

キーバリュー配列は、Bash スクリプトでデータを整理し、アクセスするための強力な方法を提供します。数値インデックスの代わりに記述的なキーを使用できるため、特に複雑なデータ構造を扱う場合に、スクリプトの可読性と保守性が向上します。

Bash のキーバリュー配列についてしっかりと理解できたので、それらを使用してシェルスクリプトを強化し、幅広いプログラミングの課題をより効率的に解決できます。