Bash 配列の要素を 1 行ごとに出力する方法

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

はじめに

このチュートリアルでは、Bash 配列について調べ、各要素を新しい行に出力する方法を学びます。これはシェルスクリプトでよくある要件です。Bash 配列を使用すると、複数の値を 1 つの変数に格納できるため、スクリプト内でデータを整理するのに不可欠です。

この実験の終わりまでに、配列の作成方法、配列要素の操作方法、および配列の内容を 1 行に 1 つずつ出力するさまざまな手法を理解するようになります。これらのスキルは、ファイルのリストを処理する、コマンドの出力を扱う、システム管理タスクを自動化するなどのタスクに対して、より効率的で読みやすいシェルスクリプトを作成するのに役立ちます。

Bash 配列の作成と理解

Bash 配列を使用すると、複数の値を 1 つの変数に格納できます。ここでは、配列の作成方法と操作方法を学びましょう。

最初の配列を作成する

WebIDE でターミナルを開きます。デフォルトでは /home/labex/project ディレクトリにいるはずです。まずは簡単な Bash スクリプトを作成しましょう。

  1. WebIDE で、エクスプローラーパネルの「New File」アイコンをクリックするか、「File > New File」メニューオプションを使用して、array_demo.sh という名前の新しいファイルを作成します。

  2. ファイルに以下の内容を追加します。

#!/bin/bash

## 果物の配列を作成する
fruits=("apple" "banana" "orange" "grape" "kiwi")

## 配列全体を出力する
echo "All fruits: ${fruits[@]}"

## 最初の要素(インデックス 0)を出力する
echo "First fruit: ${fruits[0]}"

## 3 番目の要素(インデックス 2)を出力する
echo "Third fruit: ${fruits[2]}"

## 配列内の要素の数を出力する
echo "Number of fruits: ${#fruits[@]}"
  1. Ctrl+S を押すか、「File > Save」メニューオプションを使用してファイルを保存します。

  2. 次に、ターミナルで以下のコマンドを実行して、スクリプトを実行可能にします。

chmod +x /home/labex/project/array_demo.sh
  1. スクリプトを実行します。
./array_demo.sh

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

All fruits: apple banana orange grape kiwi
First fruit: apple
Third fruit: orange
Number of fruits: 5

配列の構文を理解する

配列の構文を分解してみましょう。

  • 配列の作成: fruits=("apple" "banana" "orange" "grape" "kiwi")
    これは、5 つの要素を持つ fruits という名前の配列を作成します。

  • すべての要素にアクセスする: ${fruits[@]}
    @ 記号は、配列のすべての要素を参照します。

  • 特定の要素にアクセスする: ${fruits[0]}${fruits[2]}
    Bash の配列は 0 から始まるインデックス付けです。つまり、最初の要素はインデックス 0 にあります。

  • 配列の長さを取得する: ${#fruits[@]}
    配列参照の前に # 記号を付けると、要素の数が返されます。

配列を作成するさまざまな方法

配列を作成するさまざまな方法を示す新しいスクリプトを作成しましょう。

  1. array_creation.sh という名前の新しいファイルを作成します。
#!/bin/bash

## 方法 1: 直接宣言
colors=("red" "green" "blue" "yellow")
echo "Colors array: ${colors[@]}"

## 方法 2: 個別の要素割り当て
shapes=()
shapes[0]="circle"
shapes[1]="square"
shapes[2]="triangle"
echo "Shapes array: ${shapes[@]}"

## 方法 3: コマンド出力から配列を作成する
files=($(ls /home/labex/project))
echo "Files in current directory: ${files[@]}"

## 方法 4: 文字列から配列を作成する
data="one two three four"
numbers=($data)
echo "Numbers array: ${numbers[@]}"
  1. ファイルを保存し、実行可能にします。
chmod +x /home/labex/project/array_creation.sh
  1. スクリプトを実行します。
./array_creation.sh

作成したすべての異なる配列を示す出力が表示されるはずです。ファイル配列の正確な出力は、ディレクトリに存在するファイルによって異なります。

これらの例は、Bash 配列の柔軟性と、必要に応じてさまざまな方法で配列を作成できることを示しています。

配列要素の操作

配列の作成方法がわかったので、要素の追加、削除、変更などの操作方法を学びましょう。

配列要素の変更

配列操作を実演する新しいスクリプトを作成しましょう。

  1. WebIDE で、array_manipulation.sh という名前の新しいファイルを作成します。
#!/bin/bash

## 初期配列を作成する
fruits=("apple" "banana" "orange")
echo "Initial array: ${fruits[@]}"

## 配列の末尾に要素を追加する
fruits+=("grape")
echo "After adding grape: ${fruits[@]}"

## 複数の要素を追加する
fruits+=("kiwi" "mango")
echo "After adding kiwi and mango: ${fruits[@]}"

## 要素を変更する
fruits[1]="blueberry"
echo "After changing banana to blueberry: ${fruits[@]}"

## 要素を削除する(空のスロットが残ります)
unset fruits[2]
echo "After removing the third element: ${fruits[@]}"

## 配列のインデックスを出力する
echo "Array indices: ${!fruits[@]}"

## 空のスロットを削除するために配列を再作成する
new_fruits=()
for fruit in "${fruits[@]}"; do
  if [[ -n "$fruit" ]]; then
    new_fruits+=("$fruit")
  fi
done

fruits=("${new_fruits[@]}")
echo "After removing empty slots: ${fruits[@]}"
  1. ファイルを保存し、実行可能にします。
chmod +x /home/labex/project/array_manipulation.sh
  1. スクリプトを実行します。
./array_manipulation.sh

出力結果には、各操作によって配列がどのように変化するかが表示されます。

Initial array: apple banana orange
After adding grape: apple banana orange grape
After adding kiwi and mango: apple banana orange grape kiwi mango
After changing banana to blueberry: apple blueberry orange grape kiwi mango
After removing the third element: apple blueberry  grape kiwi mango
Array indices: 0 1 3 4 5
After removing empty slots: apple blueberry grape kiwi mango

配列のスライシング

配列の一部を抽出する方法を調べてみましょう。

  1. array_slicing.sh という名前の新しいファイルを作成します。
#!/bin/bash

## サンプル配列を作成する
colors=("red" "orange" "yellow" "green" "blue" "indigo" "violet")
echo "Full array: ${colors[@]}"

## 部分配列を抽出する(開始インデックスと長さ)
## 構文: ${array[@]:start:length}
sub_array1=("${colors[@]:1:3}")
echo "Sub-array (indices 1-3): ${sub_array1[@]}"

## あるインデックスから末尾までを抽出する
sub_array2=("${colors[@]:4}")
echo "Sub-array (from index 4 to end): ${sub_array2[@]}"

## 最後の 2 つの要素を抽出する
sub_array3=("${colors[@]: -2}") ## -2 の前のスペースに注意
echo "Last two elements: ${sub_array3[@]}"
  1. ファイルを保存し、実行可能にします。
chmod +x /home/labex/project/array_slicing.sh
  1. スクリプトを実行します。
./array_slicing.sh

出力結果には、配列をスライシングするさまざまな方法が示されます。

Full array: red orange yellow green blue indigo violet
Sub-array (indices 1-3): orange yellow green
Sub-array (from index 4 to end): blue indigo violet
Last two elements: indigo violet

配列内の要素を検索する

配列内の要素を検索する方法を実演するスクリプトを作成しましょう。

  1. array_searching.sh という名前の新しいファイルを作成します。
#!/bin/bash

## サンプル配列を作成する
fruits=("apple" "banana" "orange" "grape" "kiwi")
echo "Our fruits: ${fruits[@]}"

## 配列内で要素を検索する関数
search_array() {
  local needle="$1"
  shift
  local haystack=("$@")

  for i in "${!haystack[@]}"; do
    if [[ "${haystack[$i]}" == "$needle" ]]; then
      echo "Found '$needle' at index $i"
      return 0
    fi
  done

  echo "'$needle' not found in the array"
  return 1
}

## いくつかの果物を検索する
search_array "orange" "${fruits[@]}"
search_array "banana" "${fruits[@]}"
search_array "watermelon" "${fruits[@]}"
  1. ファイルを保存し、実行可能にします。
chmod +x /home/labex/project/array_searching.sh
  1. スクリプトを実行します。
./array_searching.sh

出力結果には、異なる要素を検索した結果が表示されます。

Our fruits: apple banana orange grape kiwi
Found 'orange' at index 2
Found 'banana' at index 1
'watermelon' not found in the array

これらの例は、Bash 配列に対して実行できる一般的な操作を示しており、スクリプトでデータのコレクションを扱うために必要な重要なスキルです。

配列要素を 1 行ごとに出力する

このステップでは、実験の主要なトピックである配列要素を 1 行ごとに出力する方法に焦点を当てます。Bash でこれを実現するさまざまな方法を探っていきましょう。

方法 1: for ループを使用する

配列要素を 1 行ごとに出力する最も簡単な方法は、for ループを使用することです。

  1. print_array_loop.sh という名前の新しいファイルを作成します。
#!/bin/bash

## サンプル配列を作成する
planets=("Mercury" "Venus" "Earth" "Mars" "Jupiter" "Saturn" "Uranus" "Neptune")

echo "Printing planets using a for loop:"
for planet in "${planets[@]}"; do
  echo "$planet"
done
  1. ファイルを保存し、実行可能にします。
chmod +x /home/labex/project/print_array_loop.sh
  1. スクリプトを実行します。
./print_array_loop.sh

出力結果には、各惑星が別々の行に表示されます。

Printing planets using a for loop:
Mercury
Venus
Earth
Mars
Jupiter
Saturn
Uranus
Neptune

方法 2: printf コマンドを使用する

printf コマンドは、echo を使ったループよりも効率的なことが多いです。

  1. print_array_printf.sh という名前の新しいファイルを作成します。
#!/bin/bash

## サンプル配列を作成する
planets=("Mercury" "Venus" "Earth" "Mars" "Jupiter" "Saturn" "Uranus" "Neptune")

echo "Printing planets using printf:"
printf "%s\n" "${planets[@]}"
  1. ファイルを保存し、実行可能にします。
chmod +x /home/labex/project/print_array_printf.sh
  1. スクリプトを実行します。
./print_array_printf.sh

出力結果は、前の方法と同じになります。

Printing planets using printf:
Mercury
Venus
Earth
Mars
Jupiter
Saturn
Uranus
Neptune

方法 3: IFS 変数を使用する

内部フィールドセパレータ (Internal Field Separator, IFS) 変数を使用すると、配列要素の出力方法を制御できます。

  1. print_array_ifs.sh という名前の新しいファイルを作成します。
#!/bin/bash

## サンプル配列を作成する
planets=("Mercury" "Venus" "Earth" "Mars" "Jupiter" "Saturn" "Uranus" "Neptune")

echo "Printing planets using IFS:"
## 一時的に IFS を改行に変更する
old_IFS="$IFS"
IFS=$'\n'
echo "${planets[*]}" ## 注意: IFS を使う場合は @ ではなく * を使用
IFS="$old_IFS"       ## 元の IFS を復元する
  1. ファイルを保存し、実行可能にします。
chmod +x /home/labex/project/print_array_ifs.sh
  1. スクリプトを実行します。
./print_array_ifs.sh

出力結果には、再び各惑星が別々の行に表示されます。

Printing planets using IFS:
Mercury
Venus
Earth
Mars
Jupiter
Saturn
Uranus
Neptune

方法 4: 複数の手法を組み合わせる

これらの手法をより包括的な例で組み合わせてみましょう。

  1. print_array_combined.sh という名前の新しいファイルを作成します。
#!/bin/bash

## サンプル配列を作成する
planets=("Mercury" "Venus" "Earth" "Mars" "Jupiter" "Saturn" "Uranus" "Neptune")

echo "Using a for loop with index:"
for i in "${!planets[@]}"; do
  echo "Planet $i: ${planets[$i]}"
done

echo -e "\nUsing printf with formatting:"
printf "Planet: %s - %d letters\n" "${planets[@]}" "${#planets[@]}"

echo -e "\nSorted planets:"
printf "%s\n" "${planets[@]}" | sort
  1. ファイルを保存し、実行可能にします。
chmod +x /home/labex/project/print_array_combined.sh
  1. スクリプトを実行します。
./print_array_combined.sh

出力結果には、配列要素をフォーマットして出力するさまざまな方法が示されます。

Using a for loop with index:
Planet 0: Mercury
Planet 1: Venus
Planet 2: Earth
Planet 3: Mars
Planet 4: Jupiter
Planet 5: Saturn
Planet 6: Uranus
Planet 7: Neptune

Using printf with formatting:
Planet: Mercury - 8 letters
Planet: Venus - 5 letters
Planet: Earth - 5 letters
Planet: Mars - 4 letters
Planet: Jupiter - 7 letters
Planet: Saturn - 6 letters
Planet: Uranus - 7 letters
Planet: Neptune - 7 letters

Sorted planets:
Earth
Jupiter
Mars
Mercury
Neptune
Saturn
Uranus
Venus

これらの各方法にはそれぞれ利点があります。

  • for ループは初心者にとって最も読みやすいです。
  • printf 方法は大きな配列に対してより効率的です。
  • IFS 方法はコンパクトですが、直感的でない場合があります。
  • 組み合わせた手法は、豊富なフォーマットオプションを提供できます。

特定のユースケースとコーディングスタイルに最適な方法を選択してください。

配列の実用的なアプリケーション

この最後のステップでは、Bash 配列の実世界でのアプリケーションを探り、配列要素を 1 行ごとに出力する手法を適用します。

ファイルリストの処理

ディレクトリ内のファイルを処理するスクリプトを作成しましょう。

  1. まず、作業対象となるサンプルファイルを作成します。
mkdir -p /home/labex/project/sample_files
touch /home/labex/project/sample_files/file1.txt
touch /home/labex/project/sample_files/file2.txt
touch /home/labex/project/sample_files/file3.txt
touch /home/labex/project/sample_files/image1.jpg
touch /home/labex/project/sample_files/image2.jpg
  1. process_files.sh という名前の新しいファイルを作成します。
#!/bin/bash

## ディレクトリ内のファイルリストを取得する
file_path="/home/labex/project/sample_files"
files=($(ls "$file_path"))

echo "All files in directory:"
printf "%s\n" "${files[@]}"

echo -e "\nProcessing text files only:"
text_files=()

## テキストファイルをフィルタリングする
for file in "${files[@]}"; do
  if [[ "$file" == *.txt ]]; then
    text_files+=("$file")
  fi
done

## 各テキストファイルを処理する
if [ ${#text_files[@]} -eq 0 ]; then
  echo "No text files found."
else
  echo "Found ${#text_files[@]} text files:"
  for file in "${text_files[@]}"; do
    echo "Processing $file..."
    ## 通常はここで各ファイルに対して何かを行います
    echo "  - Adding content to $file"
    echo "This is sample content" > "$file_path/$file"
  done
fi

## 内容を検証する
echo -e "\nContent of text files:"
for file in "${text_files[@]}"; do
  echo "--- $file ---"
  cat "$file_path/$file"
  echo "------------"
done
  1. ファイルを保存し、実行可能にします。
chmod +x /home/labex/project/process_files.sh
  1. スクリプトを実行します。
./process_files.sh

出力結果には、配列を使用してファイルを処理およびフィルタリングする方法が示されます。

All files in directory:
file1.txt
file2.txt
file3.txt
image1.jpg
image2.jpg

Processing text files only:
Found 3 text files:
Processing file1.txt...
  - Adding content to file1.txt
Processing file2.txt...
  - Adding content to file2.txt
Processing file3.txt...
  - Adding content to file3.txt

Content of text files:
--- file1.txt ---
This is sample content
------------
--- file2.txt ---
This is sample content
------------
--- file3.txt ---
This is sample content
------------

シンプルなメニューシステムの作成

配列は、スクリプト内でメニューシステムを作成するのに便利です。

  1. menu_system.sh という名前の新しいファイルを作成します。
#!/bin/bash

## メニューオプションを定義する
options=("List Files" "Check Disk Space" "Display Date" "Display Users" "Exit")

while true; do
  echo -e "\nMenu Options:"
  ## 番号付きでメニューを表示する
  for i in "${!options[@]}"; do
    echo "  $((i + 1)). ${options[$i]}"
  done

  ## ユーザーの選択を取得する
  read -p "Enter your choice (1-${#options[@]}): " choice

  ## 0 から始まるインデックスに変換する
  ((choice--))

  ## 選択を処理する
  case $choice in
    0) ## List Files
      echo -e "\nFiles in current directory:"
      ls -la /home/labex/project
      ;;
    1) ## Check Disk Space
      echo -e "\nDisk space usage:"
      df -h
      ;;
    2) ## Display Date
      echo -e "\nCurrent date and time:"
      date
      ;;
    3) ## Display Users
      echo -e "\nCurrently logged in users:"
      who
      ;;
    4) ## Exit
      echo "Exiting menu system. Goodbye!"
      exit 0
      ;;
    *)
      echo "Invalid choice. Please try again."
      ;;
  esac

  ## メニューを再表示する前に一時停止する
  read -p "Press Enter to continue..."
done
  1. ファイルを保存し、実行可能にします。
chmod +x /home/labex/project/menu_system.sh
  1. スクリプトを実行します。
./menu_system.sh
  1. メニューシステムが表示されます。異なるオプションを選択して結果を確認してみてください。終了するには、オプション 5 を選択します。

コマンド出力の処理

配列は、コマンドの出力を処理するのに最適です。

  1. process_command_output.sh という名前の新しいファイルを作成します。
#!/bin/bash

## 実行中のプロセスのリストを取得する
echo "Getting list of processes..."
processes=($(ps -e | awk '{print $4}' | tail -n +2))

echo "Found ${#processes[@]} processes"
echo -e "\nTop 10 processes:"
printf "%s\n" "${processes[@]:0:10}"

## 一意のプロセスをカウントする
echo -e "\nCounting unique process names..."
declare -A process_count

for process in "${processes[@]}"; do
  ((process_count["$process"]++))
done

echo -e "\nProcess Count Summary:"
for process in "${!process_count[@]}"; do
  echo "$process: ${process_count["$process"]}"
done | sort -rn -k2 | head -10
  1. ファイルを保存し、実行可能にします。
chmod +x /home/labex/project/process_command_output.sh
  1. スクリプトを実行します。
./process_command_output.sh

出力結果には、配列を使用してコマンド出力を処理する方法が示されます。正確な出力は、システムで実行中のプロセスによって異なります。

これらの例は、Bash 配列が実世界のシナリオで実用的な問題を解決するためにどのように使用できるかを示しています。アイテムのリストを処理し、読みやすい形式で出力する能力は、シェルスクリプトの基本的なスキルです。

まとめ

この実験では、Bash 配列を扱うための重要なスキルを学びました。

  1. 配列の作成と理解

    • さまざまな方法で配列を宣言する
    • 配列要素とプロパティにアクセスする
  2. 配列要素の操作

    • 要素の追加、削除、および変更
    • 配列のスライスと要素の検索
  3. 配列要素を 1 行ごとに出力する

    • for ループを使用して配列を反復処理する
    • 効率的な出力のために printf コマンドを使用する
    • カスタムフォーマットのために IFS 変数を活用する
    • 高度な出力フォーマットのために手法を組み合わせる
  4. 実用的なアプリケーション

    • ファイルリストの処理
    • メニューシステムの作成
    • コマンド出力の処理

これらのスキルは、Bash スクリプトで配列を使用するための堅固な基礎を提供します。これで、データのコレクションを効率的に保存、操作、および表示できるようになり、スクリプトをより堅牢で汎用的なものにすることができます。

Bash 配列を習得するためのポイントは練習であることを忘れないでください。これらの手法を自分のスクリプトに取り入れ、実世界の問題を効率的に解決するのにどのように役立つかを探ってみてください。