関数へ処理をまとめる
関数は、名前を付けた処理のまとまりです。呼び出し側から処理の目的が分かる名前を付けると、スクリプト全体を読みやすくできます。
メッセージ関数BASH
print_line() {
printf '%s\n' '----------------'
}
print_line
printf 'レポート\n'
print_line実行結果OUTPUT
----------------
レポート
----------------関数を定義しただけでは実行されません。定義のあとで関数名を書いて呼び出します。
位置パラメーターで引数を受け取る
関数内の$1、$2は関数へ渡した引数です。スクリプト全体では、コマンドライン引数を表します。
show.shBASH
show_file() {
local path="$1"
printf '対象: %s\n' "$path"
}
if [[ $# -ne 1 ]]; then
printf '使い方: %s ファイル\n' "$0" >&2
exit 2
fi
show_file "$1"実行例COMMAND
bash show.sh data/app.log実行結果OUTPUT
対象: data/app.log$#は引数の個数、$0はスクリプト名です。引数の個数を確認せずに$1を使うと、入力漏れで分かりにくいエラーになることがあります。
終了ステータスを返す
関数は値を返すというより、成功・失敗を終了ステータスで返す設計がよく使われます。成功を0、失敗を1以上にします。
読み取り可能か返すBASH
is_readable() {
[[ -r "$1" ]]
}
if is_readable 'data/app.log'; then
printf '読み取り可能です。\n'
else
printf '読み取れません。\n' >&2
fi実行結果OUTPUT
読み取り可能です。関数の最後に実行した[[ ... ]]の結果がそのまま戻り値になります。文字列を返したい場合は、表示と終了ステータスを分ける設計を検討します。
localで変数の範囲を限定する
Bashの関数内でlocalを付けた変数は、その関数の中だけで使います。外側の変数を誤って上書きしないために、関数内の一時変数へ付けます。
localを使うBASH
make_message() {
local subject="$1"
printf '件名: %s\n' "$subject"
}
subject='外側の値'
make_message 'レポート'
printf '外側: %s\n' "$subject"実行結果OUTPUT
件名: レポート
外側: 外側の値getoptsでオプションを受け取る
実用的なスクリプトでは、-fや-nのようなオプションを受け取ることがあります。Bashのgetoptsを使うと、形式をそろえて処理できます。
greet.shBASH
name='world'
while getopts 'n:' option; do
case "$option" in
n) name="$OPTARG" ;;
*) printf '使い方: %s [-n 名前]\n' "$0" >&2; exit 2 ;;
esac
done
printf 'こんにちは、%sさん。\n' "$name"実行例COMMAND / OUTPUT
bash greet.sh -n Mity
こんにちは、Mityさん。n:のコロンは、-nに値が必要という意味です。複雑な引数仕様にする前に、使い方とエラー時の終了コードを決めておきます。
練習:ファイルの行数を調べる関数
ファイルパスを引数に受け取り、存在しなければエラー、存在すれば行数を表示するスクリプトを作ってください。
count.shBASH
count_lines() {
local file="$1"
if [[ ! -f "$file" ]]; then
printf 'ファイルがありません: %s\n' "$file" >&2
return 1
fi
wc -l < "$file"
}
if [[ $# -ne 1 ]]; then
printf '使い方: %s ファイル\n' "$0" >&2
exit 2
fi
printf '行数: %s\n' "$(count_lines "$1")"実行例COMMAND / OUTPUT
bash count.sh data/app.log
行数: 3次は安全なスクリプトと定期実行へ進み、失敗時の扱いやログを考えます。