関数の引数と戻り値
| 対応: | 全Linux | |
|---|---|---|
| macOS(2001 Cheetah) | ||
| Bash 1.0(1989) |
シェル関数に渡された引数は『$1』〜『$9』、10番目以降は『${10}』で参照します。『$@』で全引数を配列的に、『$#』で引数の個数を取得できます。戻り値は終了ステータス(return)か標準出力(echo)で返します。
構文
引数を参照します。
function_name() {
local first="$1" # 第1引数
local second="$2" # 第2引数
local all=("$@") # 全引数を配列に
local count=$# # 引数の個数
}
終了ステータスで結果を返します(0=成功、1以上=失敗)。
return 0 return 1
文字列を返します(echo + $() でキャプチャ)。
echo "返したい値"
呼び出し元でキャプチャします。
result=$(function_name 引数)
引数・戻り値の仕組み一覧
| 項目 | 概要 |
|---|---|
| $1 〜 $9 | 関数に渡された第1〜第9引数です。 |
| ${10} 以降 | 10番目以降の引数は波括弧が必要です。 |
| $@ | 全引数をリストとして参照します(スペース含む引数も安全)。 |
| $* | 全引数を IFS 区切りの1文字列として参照します。 |
| $# | 引数の個数です。 |
| return N | 終了ステータス N(0〜255)を返して関数を終了します。 |
| echo "値" | 文字列の値を標準出力に出力します($() でキャプチャして使います)。 |
| $? | 直前の関数(またはコマンド)の終了ステータスを参照します。 |
| shift | 位置パラメータを左に1つずらします($2→$1、$3→$2 ...)。 |
サンプルコード
ターミナルで直接関数を定義して引数を渡します。『{』の後で Enter を押すと『> 』マークが表示され、これは「まだ入力が続く」というサインで、『}』を入力すると定義が完了します。
greet() {
echo "こんにちは、$1 さん!"
echo "あなたは $2 歳ですね"
}
greet "狡噛慎也" 28
こんにちは、狡噛慎也 さん!
あなたは 28 歳ですね
『$1』〜『$9』で引数を参照し、『$#』で個数、『$@』で全引数を取得します。
sample_show_args.sh
#!/bin/bash
show_args() {
echo "引数の個数: $#"
echo "第1引数: $1"
echo "第2引数: $2"
echo "全引数: $@"
}
show_args "Kogami Shinya" "Tsunemori Akane" "Ginoza Nobuchika"
実行するコマンドは次の通りです。
bash show_args.sh 引数の個数: 3 第1引数: Kogami Shinya 第2引数: Tsunemori Akane 全引数: Kogami Shinya Tsunemori Akane Ginoza Nobuchika
引数の個数をチェックし、足りなければエラーを返します。『${2:-デフォルト値}』で省略可能な引数にデフォルト値を設定できます。
sample_create_backup.sh
create_backup() {
if [ $# -lt 1 ]; then
echo "エラー: ファイルパスを指定してください" >&2
return 1
fi
local src="$1"
local dst="${2:-${src}.bak}" # 第2引数がなければ .bak を付ける
cp "$src" "$dst"
echo "$src → $dst にバックアップしました"
return 0
}
create_backup "/etc/hosts" "/tmp/hosts.bak"
echo "終了ステータス: $?"
create_backup # 引数なし → エラー
echo "終了ステータス: $?"
実行するコマンドは次の通りです。
bash create_backup.sh /etc/hosts → /tmp/hosts.bak にバックアップしました 終了ステータス: 0 エラー: ファイルパスを指定してください 終了ステータス: 1
『shift』で位置パラメータを左にずらしながら順番に処理します。
sample_process_all.sh
process_all() {
while [ $# -gt 0 ]; do
echo "処理中: $1"
shift
done
}
process_all "Kogami Shinya" "Tsunemori Akane" "Ginoza Nobuchika" "Masaoka Tomomi"
実行するコマンドは次の通りです。
bash process_all.sh 処理中: Kogami Shinya 処理中: Tsunemori Akane 処理中: Ginoza Nobuchika 処理中: Masaoka Tomomi
『"$@"』を使うと、スペースを含む引数も安全に扱えます。
sample_print_each.sh
print_each() {
for item in "$@"; do
echo " [$item]"
done
}
print_each "Kogami Shinya" "Tsunemori Akane" "Ginoza Nobuchika"
実行するコマンドは次の通りです。
bash print_each.sh [Kogami Shinya] [Tsunemori Akane] [Ginoza Nobuchika]
『echo』で文字列を出力し、呼び出し元で『$()』でキャプチャして値を受け取ります。
sample_to_upper.sh
to_upper() {
echo "${1^^}"
}
result=$(to_upper "hello bash")
echo "大文字: $result"
実行するコマンドは次の通りです。
bash to_upper.sh 大文字: HELLO BASH
概要
関数の引数(位置パラメータ)はスクリプト自体の引数とは別のスコープです。関数内で『$1』を参照すると関数の引数が得られ、スクリプトの引数は隠れます。スクリプトの引数を関数内で使いたい場合は、呼び出し前に別変数に保存しておきます。
『"$@"』はスペースを含む引数を安全に扱えます。引数をそのまま別の関数やコマンドに渡すときは『"$@"』が使われます。『$*』や『$@』(クォートなし)はスペースで分割されてしまいます。
関数の定義の基本は 関数の定義と呼び出し を参照してください。
よくあるミス
よくあるミス1: return で文字列を返そうとする
return は終了ステータス(整数)しか返せません。文字列を return しようとするとエラーになります。
get_name() {
return "狡噛慎也"
}
修正後は次の通りです。
bash get_name.sh bash: return: 狡噛慎也: numeric argument required
文字列の「返却」は echo で出力してコマンド置換でキャプチャします。
get_name() {
echo "狡噛慎也"
}
name=$(get_name)
echo "$name"
よくあるミス2: "$@" をクォートせずに渡すとスペース入り引数が分割される
引数を別の関数に渡すとき、クォートなしの $@ を使うとスペースを含む引数が分割されます。
run() {
echo "引数: $1"
}
run $@
修正後は次の通りです。
bash test.sh "Kogami Shinya" 引数: Kogami
クォートした "$@" を使うと各引数がそのまま渡されます。
bash test.sh "Kogami Shinya" 引数: Kogami Shinya
記事の間違いや著作権の侵害等ございましたらお手数ですがこちらまでご連絡頂ければ幸いです。