導入
関数から値を持ち帰りたい。ここで多くの人が return を使おうとして混乱します。シェルの return は値ではなく成功/失敗を返すもの。値を返したいときは別の方法を使います。
説明
シェルの関数には、2つの「返し方」があります。
| 返したいもの | 方法 | 受け取り方 |
|---|---|---|
| 成功/失敗 | return 0 / return 1 | if 関数名; then や $? |
| 値(文字列・数値) | echo 値 | 結果=$(関数名) |
#!/bin/bash
# 値を返す: echo して $( ) で受け取る
count_lines() {
wc -l < "$1"
}
# 成功/失敗を返す: return して if で受け取る
file_exists() {
if [ -f "$1" ]; then
return 0
else
return 1
fi
}
lines=$(count_lines logs/app.log)
echo "app.log は $lines 行です"
if file_exists data.csv; then
echo "data.csv はあります"
else
echo "data.csv はありません"
fi
return に書けるのは 0〜255 の終了ステータスです。「関数の中で計算した合計」を return で返そうとすると、256以上は化けますし、そもそも文字列は返せません。
値を返すときは echo。呼ぶ側は $( ) で拾う。この形が唯一の正解と思って構いません。
flowchart TD
A["count_lines logs/app.log"] --> B["関数の中で echo 8"]
B --> C["$(count_lines …) が 8 を受け取る"]
C --> D["lines=8"]
注意点として、値を返す関数の中で余計な echo をしないこと。デバッグ用の echo "処理中" が混ざると、それも戻り値の一部になってしまいます。途中経過を出したいときは、標準エラー出力へ(echo "処理中" >&2)逃がします。
やってみよう
スクリプトを実行して、行数の取得と存在チェックが動くことを確かめましょう。次に count_lines logs/access.log に変えて数が変わること、file_exists nothing.csv にして else 側に落ちることを試してください。
演習
count_lines 関数を使って logs/access.log の行数を取得し、アクセスログ: 10 行 と表示してください。
ヒント1を見る
n=$(count_lines logs/access.log) で受け取れます。
ヒント2を見る
echo "アクセスログ: $n 行"