Bashの関数の使い方: コマンドのように呼び出す関数の定義
目次
- Bashの関数の使い方
- 関数とは?
- Bashの関数の作り方
- Bashの関数の呼び出し方
- Bashの関数の引数
- Bashの関数の出力を代入する
- Bashの関数の返り値
- 関数内の変数のスコープ
- 使用例
- 問題
Bashの関数の使い方
Bash(バッシュ)というのはシェルでありスクリプト言語です。
このBashで書かれたスクリプトでは関数を使うことが出来ます。
処理が長くなったら関数に分割して処理を分けるのが定石です。
↓は「Hello!」と出力するBashの関数のサンプルコードです。
function hello() { echo "Hello!" } hello # Hello!
この記事ではBashの関数について具体的に↓を見ていきたいと思います。
関数とは?
Bashの関数の作り方
Bashの関数の呼び出し方
Bashの関数の引数
Bashの関数の出力を代入する
Bashの関数の返り値
関数内の変数のスコープ
使用例
関数とは?
プログラミングにおける関数とは、処理のまとまりのことです。
長くなった処理(コード)を関数に切り分けることでプログラム全体の見通しが良くなって、プログラムの品質を上げることができます。
関数には入力と出力があります。
関数の引数(ひきすう)によって関数に入力を渡すことができます。
引数とは関数を呼び出す時に渡す外部からの入力のことです。
たとえばBashではfunc
という関数が存在する場合、↓のようにfunc
という関数を呼び出しますが、
func
この時に関数func
の呼び出し時に渡すのが引数です。
引数はたとえば↓のように(1 2 3
というのが引数)渡すことができます。
func 1 2 3
関数の出力とは、関数の返り値と関数内の出力のことです。
関数を呼び出し、関数がいろいろな処理をやった後に、呼び出し側に返す値を返り値といいます。
Bashの関数の返り値は↓のように$?
で参照することができます。
func if [ $? -eq 0 ]; then echo success fi
Bashは一般的なプログラミング言語の文法に比べると、だいぶ毛色が違う文法を持っていますが、これはBashがコマンドを中心に記述するシェルスクリプトだからです。
Bashはコマンドを使うことを第1に考えて設計されています。そのため他のPythonやRubyなどのプログラミング言語に比べると変わっています。
しかし慣れると合理的な文法になっていることがわかると思います。
この記事ではBashで使う基本的な機能と文法について記述していきます。
Bashの関数の作り方
Bashの関数は↓のフォーマットで記述します。
function 関数名() { 処理 }
最初にfunction
というキーワードを書き、その次に関数名を書きます。
関数名の後にはカッコ(()
)を書き、それからブレース(波括弧、{}
)を書きます。
関数名の前にあるfunction
は省略することが出来ます。
function
を省略した場合は↓のようなフォーマットになります。
関数名() { 処理 }
たとえばfunc
という関数を定義してみると、Bashでは↓のように書くことが出来ます。
function func() { return 0 }
return 0
というのは返り値を返しています。
関数名にはアンダーバーやハイフン、大小英数字のほか、日本語も使うことが出来ます。
function あばば() { return 0 } function _abc-DEF123.456() { return 0 }
(^ _ ^) | ハイフンやドットも使える! |
Bashはコマンドを実行するためのスクリプトなので、コマンドの命名規則を関数名に流用することが出来ます。
コマンドの命名規則とは、つまりファイル名ということです。
Bashの関数の呼び出し方
Bashの関数は、コマンドのように呼び出します。
つまり、関数名の後にカッコをつけません。
function hi() { echo "Hi" } # ↓ここで呼び出し hi # Hi
なぜこのような関数呼び出しになっているのでしょうか。
他のコンパイラ言語やインタプリタ言語から来た人は頭にクエッションマークですよね。
これもBashがコマンドを中心に扱うスクリプト言語であることに由来します。
関数の呼び出しもコマンドのように行えるようにすることで、他のコマンド呼び出しと区別せずに使えるようになるんですね。
つまりBashにおいてはこっちが普通で、このほうが便利なわけです。
Bashの関数の引数
Bashの関数には引数を渡すことが出来ます。
これも普通のコマンドのように指定できます。
hi 1 2 3
この引数を関数内で参照するには↓のようにします。
function hi() { echo Hi $1 echo Hi $2 echo Hi $3 } hi 1 2 3 # Hi 1 # Hi 2 # Hi 3
関数に渡された1
番目の引数は$1
で参照し、2
番目は$2
, 3
番目は$3
のように参照します。
Bashの関数の引数はこのように$
に数字をつけて参照します。
他にも↓のような特殊変数を参照できます。
$0 ... ファイル名
$# ... 関数の引数の総数
$1 ~ $n ... 引数
$* ... 全引数リスト。「"」で囲むと"$1 $2 ..."のように展開される。
$@ ... 全引数リスト。「"」で囲むと"$1" "$2" ... のように引数ごとにダブルクオートで囲まれ展開される
$? ... 最後に実行したコマンドの返り値
これらの変数を使ったサンプルは↓のようになります。
function allstar() { echo ファイル名: $0 echo 引数の総数: $# echo 1番目の引数: $1 echo 2番目の引数: $2 echo 3番目の引数: $3 echo 全引数リスト1: "$*" echo 全引数リスト2: "$@" echo 返り値: $? } allstar cat dog bird
出力結果。
ファイル名: a.sh 引数の総数: 3 1番目の引数: cat 2番目の引数: dog 3番目の引数: bird 全引数リスト1: cat dog bird 全引数リスト2: cat dog bird 返り値: 0
$*
と$@
の違いがわかりづらいですが、これはfor
文で回してみるとよくわかります。
function hi() { echo "\$*の場合" for el in "$*"; do echo $el done echo "" echo "\$@の場合" for el in "$@"; do echo $el done } hi cat dog bird
出力結果。
$*の場合 cat dog bird $@の場合 cat dog bird
$*
はfor
文で回すと全ての引数が1行の文字列として処理されますが、$@
は引数ごとに処理されているのがわかります。
Bashの関数の出力を代入する
Bashの関数の出力は、関数名をバッククオートで囲むと左辺の変数に関数の出力を代入することが出来ます。
function hi() { echo Hi } result=`hi` echo result: $result # result: Hi
バッククオートの他には$()
も使えます。
function hi() { echo Hi } result=$(hi) echo result: $result # result: Hi
バッククオートは入れ子にできませんが、$()
は入れ子に出来る特徴があります。
拡張性を考えた場合は$()
、手軽さならバッククオートになりそうです。
Bashの関数の返り値
Bashの関数は返り値を返すことが出来ます。
返り値を返すにはreturn
を使います。
この返り値を参照するには、関数の実行直後に$?
を参照します。
function dogs() { return 101 } dogs echo $? # 101
関数内にreturn
が無い場合はデフォルトで最後のコマンドの実行結果になります
↓の場合、fail_test
の返り値に注目してください。
function fail_1() { return 1 } function fail_2() { return 2 } function fail_test() { fail_1 fail_2 } fail_test echo $? # 2
返り値は0
が正常終了、0
以外が異常終了が慣例になっています。
Bashの関数は明示的、あるいは暗黙的に返り値を返しますが、これらの関数の組み合わせには&&
を使うことが出来ます。
function one() { echo "one" return 0 } function two() { echo "two" return 1 } function three() { echo "three?" return 0 } one && two && three # one # two
↑の場合、two
関数が異常終了の返り値(1
)を返すので、最後のthree
は実行されずにコマンドラインが終了します。
関数内の変数のスコープ
関数内で定義した変数はデフォルトでグローバルスコープになります。
↓の場合、変数a
は関数の外からも参照できます。
function hi() { a=1 } hi echo $a # 1
変数をローカルにしたい場合は変数名の前にlocal
を付けます。
function hi() { local a=1 } hi echo $a # 出力なし
使用例
Bashの関数の使用例です。
findとgrepを抽象化する
find
とgrep
を抽象化して関数にします。
function look() { find "$1" -type f | grep "$2" } look /tmp "my-dust" # /tmp/my-dust.txt
lsを抽象化する
ls
を抽象化して、番号でファイル名を参照できるようにします。
function lsf() { arr=(`ls "$1"`) echo ${arr[$2]} } lsf /tmp 2 # a.txt
問題
Q1: Bashの関数の定義で、関数名の前に付けるものを答えよ
func
function
fn
Q2: Bashの関数内の変数で、$#
の変数の意味を答えよ
ファイル名
最後に実行したコマンドの返り値
関数の引数の総数
Q3: Bashの関数で返り値を返したい時に使われる文を答えよ
return
echo
find
答え
Q1: 2
Q2: 3
Q3: 1