関数(基本)

関数というものをご存知でしょうか?
Excelなどにもありますので、パソコンを触った事のある人だったら聞いた事ぐらいははあるだろうと思います。
関数とは簡単に言うと、「小さな処理の塊」とでも表現すれば良いのでしょうか。
ある一連の処理をまとめた物の事を指します。

bashなどのスクリプト言語では、処理を関数化する事はとても重要です。
関数化を行わないと、冗長(同じ様な事の繰り返し)な処理が増える傾向があるからです。
同じ様な処理がひとつのプログラム内で繰り返されると、非常に可読性が悪くなり、それと同時に長いプログラムになるのでメンテナンス性も悪くなります。

関数化をするのは簡単です。
まとめたい処理の先頭と終わりを以下の様に括ってあげます。

function 関数名
{
    実行する処理群
}

そして、上記のようにまとめた関数を、スクリプトの最初の方に記述します。
bashスクリプトは実行されると最初の行から順に読み込んでいきますので、関数の呼び出しがあった時に関数が読み込まれていなければならないからです。

bashスクリプトでは(と言うよりも私の場合)、まず、簡単に一連の処理の最初から最後までフロー(処理の流れ)を考え、その中で冗長な処理や、ある程度まとまった処理をを関数化し、メインのフローでは、制御部分だけを書き、処理部分はほとんど関数を呼び出す形にします。
こうやって、メインのスクリプトの流れと、細かい処理部分を分ける事でデバッグも楽になりますし、大規模なスクリプトであれば、複数人数での開発等も可能となります(但し、フローなどの仕様は事前に決めておく必要があります)。

メインのフローから関数を呼び出した場合、処理結果をメインのフロー側で受け取る必要があります。
以前、戻り値を取得する方法(「$?」によって取得する)を説明しましたが、同じ様に、関数の処理結果も特殊変数の「$?」で取得する事ができます。
但し、「exit」コマンドを使用して関数内で戻り値を出力すると、その時点でスクリプトは終了してしまいますので、関数の場合、「return」コマンドを使用して戻り値を出力します。
使い方は「exit」コマンドと一緒です。

return 戻り値

では、試しに以下のスクリプトの処理を関数化してみましょう。

#!/bin/bash

## メインフロー
## 「ls -l」コマンドを実行し、出力する。

ls -l

exit 0

関数化するとこうなります。

#!/bin/bash

## 関数を定義

function F_LsOutput
{
    ## 「ls -l」コマンドを実行し、出力する。

    ls -l
    if [ $? -eq 0 ]
    then
        return 0
    else
        return 1
    fi
    return 1
}

## メインフロー

## 関数を呼び出す

F_LsOutput

## 関数の戻り値を取得する

if [ $? -eq 0 ]
then
    echo "正常終了"
else
    echo "異常終了"
    exit 1
fi
exit 0

どうでしょうか?
馬鹿みたいに長くなってしまいましたね。
これは、関数内で実行するコマンドと関数からの戻り値の判定処理を入れたからです。

「関数化する=複数回その処理を使う可能性がある」と考えるべきです。
関数内でバグが発生した場合、その関数を呼び出した回数だけバグが発生する可能性があると言う事です。
ですので、関数内の例外処理はしっかりと行いましょう。
「なんか関数化するの面倒臭いなー」とか思った人は、逆に考えてみてください。
冗長な処理をそのまま記述した場合、デバッグ箇所はその処理の回数だけありますが、関数化されていれば1回で終わります。(要はメンテナンス性が上がると言うことです)

だからと言って、むやみに関数化すると、これはこれで可読性が悪くなります。
適度に関数化する様にしましょう。