Bashプログラミング
 Computer >> コンピューター >  >> プログラミング >> Bashプログラミング

Bash/シェルスクリプトのコマンドライン引数の使い方【getopts・位置パラメータ・ループを徹底解説】

このチュートリアルでは、Bashスクリプトにコマンドライン引数を渡す方法を解説します。そのまま使えるサンプルコードを豊富に交えて説明するので、初めての方でもすぐに取り掛かれます。

Bash/シェルスクリプトは、Linux上の日々の作業を自動化し、業務効率を大きく高めてくれる強力な道具です。定型処理をスクリプトに任せれば、単純作業にかかる時間をぐっと削減できます。

さらに、スクリプトを「再利用できる形」にしておくと便利さが一段と増します。同じタスクでも対象データや実行日によって内容が変わる場合、いちいちスクリプトを書き直す必要はありません。同じスクリプトを使い回し、実行時にパラメータ(引数)を渡すだけで済みます。これがいわゆる「コマンドライン引数」の利用です

例えば、テキストをファイルに出力するスクリプトを考えてみましょう。引数がなければ、出力先のファイル名を変えるたびにスクリプト自体を編集しなければなりません。複数のファイルに出力したければ、スクリプトのコピーを複数用意することになるかもしれません。しかし引数を使えば、1つのスクリプトで任意の名前・任意の数のファイルに出力できるようになります。

引数(オプションとその)の渡し方にはいくつかの方式があり、目的に応じて使い分けるのがポイントです。以下、代表的な3つの方法をサンプル付きで紹介します。

方法1:getopts(フラグ方式)でコマンドライン入力を読み取る

  • getoptsは、コマンドラインからオプション(フラグ)を取得し、その(引数)をスクリプト内で使えるようにするシェル組み込みコマンドです。
    • オプションは「-(ダッシュ)+英字1文字」で表し、続けて値を渡します(例:-v value)。
  • 引数を渡す順序が固定されないため、柔軟な指定が可能です。
  • ここで紹介する中では最も汎用性が高く、特別な理由がなければまずこの方法を選ぶのがおすすめです。

getoptsを使ったBashスクリプトの例

次のサンプルスクリプトは、ファストフードの注文を受け付けるもので、3つのオプションを受け取ります。

  • -o:注文内容(order)
  • -s:サイズ(size)
  • -d:ドリンク(drink)

fastFoodOrder.sh

#!/bin/bash

# whileループでオプション o / s / d を順番に解析する
while getopts o:s:d: flag
do

    # case文で、$flag に代入された各オプションを処理に振り分ける
    # OPTARG には getopts が受け取った値が入り、フラグごとに対応する変数へ代入される
    case "${flag}" in
        o) order=${OPTARG};;
        s) size=${OPTARG};;
        d) drink=${OPTARG};;
    esac

done

# オプションに渡された値は、それぞれ対応する変数から参照できる
echo "Order: $order";
echo "Size: $size";
echo "Drink: $drink";

なお、スクリプト1行目の#!/bin/bash(シバン)は「このスクリプトをbashで実行する」という宣言です。詳細は別記事で解説しています。

実行するには、次のように入力します。

bash ./fastFoodOrder.sh -d Cola -o 'Fish Burger Meal' -s Large

実行結果:

Order: Fish Burger Meal
Size: Large
Drink: Cola

出力を見ると分かるように、オプションを指定する順序は自由です。-d を先に書いても -o を先に書いても、正しく解析されます。

補足:実行時に「./」を付けるのは、カレントディレクトリ内のスクリプトであることを明示するためです(PATHにカレントディレクトリは通常含まれていないため)。

同じオプションに複数の値を渡す

1つのオプションを複数回指定して、複数の値を渡すこともできます。受け取った値は配列としてスクリプト内で扱えます。

複数の値を1つのオプションに渡すなら、この方法がベストです。クォートで囲む方式や区切り文字を使う方式では値に使える文字が制限されますが、この方法ならどんな文字でも値として渡せます。

fastFoodOrderExtras.sh

#!/bin/bash

# whileループでオプション o / s / d / e を順番に解析する
while getopts o:s:d:e: flag
do

    # case文で、$flag に代入された各オプションを処理に振り分ける
    # OPTARG には getopts が受け取った値が入る
    case "${flag}" in
        o) order=${OPTARG};;
        s) size=${OPTARG};;
        d) drink=${OPTARG};;
        e) extras+=("$OPTARG");; # -e が指定されるたびに、配列 extras の末尾へ値を追加
    esac

done

# オプションに渡された値は、それぞれ対応する変数から参照できる
echo "Order: $order";
echo "Size: $size";
echo "Drink: $drink";
echo "The list of extras is '${extras[@]}'"

# 追加トッピング(extras)の値を1つずつ取り出して表示
for val in "${extras[@]}"; do
    echo $val
done

このスクリプトは、追加トッピングを指定する -e オプションを何度でも繰り返し指定できます。

bash ./fastFoodOrderExtras.sh -d Cola -o 'Fish Burger Meal' -s Large -e Sauce -e Salt -e Pepper

実行結果:

Order: Fish Burger Meal
Size: Large
Drink: Cola
The list of extras is 'Sauce Salt Pepper'
Sauce
Salt
Pepper

方法2:位置パラメータを使う

  • 引数の個数と並び順があらかじめ決まっている場合に使う方法です。
  • 仕組みがシンプルなので、小規模なスクリプトに向いています。

fastFoodOrder.sh

#!/bin/bash

echo "Order: $1";
echo "Size: $2";
echo "Drink: $3";

$1、$2、$3…という特殊変数には、コマンドラインで渡された引数が左から順番に格納されます。実行してみましょう。

bash ./fastFoodOrder.sh 'Fish Burger Meal' Large Cola

実行結果:

Order: Fish Burger Meal
Size: Large
Drink: Cola

この方法では引数の順序がすべてです。順番を入れ替えると、値が別の変数に代入されてしまいます。

bash ./fastFoodOrder.sh 'Fish Burger Meal' Cola Large

実行結果(意図どおりに代入されていない):

Order: Fish Burger Meal
Size: Cola
Drink: Large

補足:引数の総数は$#、スクリプト名は$0で参照できます。また、10番目以降の引数は${10}のように波括弧で囲んで参照します。

方法3:ループでコマンドライン引数を読み取る

  • 引数の個数が事前に分からない場合に最適な方法です。
    • 例えば、レシピの材料リストのように、渡される項目の数がその都度変わるケースなどが該当します。
  • 組み込み変数$@(ユーザーが渡した全引数を格納した配列)を利用します。

recipe.sh

#!/bin/bash

i=1; # ループの回数を数えるイテレータ(カウンタ)

for ingredient in "$@" # 渡された全引数を格納する配列 $@ を順にループ
do
    echo "Ingredient number $i is $ingredient"; # 呼び出し時に渡された材料を表示
    i=$((i + 1)); # イテレータをインクリメントしてループ回数を記録
done

実行:

sh ./recipe.sh bread lettuce cheese hamburger

実行結果:

Ingredient number 1 is bread
Ingredient number 2 is lettuce
Ingredient number 3 is cheese
Ingredient number 4 is hamburger

このように、引数の数がいくつであっても、forループと $@ を組み合わせればすべて自動的に処理できます。

まとめ:使い分けの目安

  • getopts:オプション形式(-o など)で柔軟に指定させたい場合。順序不問で、最もおすすめの方法。
  • 位置パラメータ:引数の個数・順序が固定のシンプルなスクリプト向け。
  • ループ+$@:引数の個数が不定の場合向け。

用途に合わせてこれらを使い分ければ、再利用性が高く実用的なシェルスクリプトを作れるようになります。

  1. Linuxで効果的なBashスクリプトを書くための実践テクニック10選

    シェルスクリプトは、Linuxで学べる最も手軽なプログラミング手法のひとつです。システム管理におけるタスクの自動化や、簡単なユーティリティ・ツールの開発など、管理者にとって必須のスキルとも言えます。 本記事では、効果的かつ信頼性の高いbashスクリプトを書くために役立つ、実用的な10のヒントを紹介します。 1. スクリプトには必ずコメントを書く これはシェルスクリプトに限らず、あらゆるプログラミングで推奨される基本プラクティスです。コメントを適切に記述しておけば、後から自分や他の人がスクリプトを読んだときに、各部分が何をしているのかを素早く理解できます。 コメントは # 記号で定義します。 #

  2. Windows 10にBash(Linuxシェル)をインストールして使う方法【WSL完全ガイド】

    Windows上でLinuxシェルをセットアップして使う方法を、Windows Subsystem for Linux(WSL)を使って解説します。 このチュートリアルは、2020年以降にリリースされた最新版のWindows 10を対象としています。古いバージョンのWindows 10でのWSLの使い方や、Windows 8/7/XP向けの別の方法については扱いません。サポートが終了したソフトウェアの使用は避けるべきだからです。どうしてもWindowsを使わなければならない場合は、必ずセキュリティ更新プログラムが提供されているバージョンを使用してください。 WSLは非常に優れたツールで、まるで