bash
関数を定義するためにキーワードを使用または省略できますfunction
。違いはありますか?
#!/bin/bash
function foo() {
echo "foo"
}
bar() {
echo "bar"
}
foo
bar
関数への呼び出しはすべてfoo
成功し、bar
違いは見られません。それで、これが単に可読性のためであるのか、それとも何か抜けたのかどうか疑問に思います。
ただし、他のシェル(dash
debian / ubuntuの/bin/sh
シンボリックリンクなどdash
)では、キーワードを使用すると失敗しますfunction
。
ベストアンサー1
2つの異なる構文がある理由は歴史的です。キーワードfunction
のソースケシ。 C()
に触発された構文ボンシェル。POSIXBournefoo ()
構文のみが標準化されています。 Bashとzshは混合だけでなく両方をサポートしますfunction foo () { … }
。生成された関数は、ATT kshを除いてはまったく同じです。
構文の落とし穴に注意してください()
。関数名はエイリアス拡張の影響を受けます。
alias f=g
f () { echo foo; }
type f # f is an alias for g
type g # g is a shell function
f # alias f → function g → print foo
\f # no alias lookup → f: not found
g # function g
function
ATT ksh (pdksh や mksh などの子を除く) では、Bourne/POSIX 構文で定義された関数と Bourne/POSIX 構文で定義された関数とにはいくつかの違いがあります。で定義した関数内で、このキーワードfunction
はtypeset
ローカル変数を宣言します。関数が終了すると、この変数の値は関数を開始する前の値にリセットされます。クラシック構文を使用すると、typeset
変数は使用するかどうかにかかわらず、グローバルスコープを持ちます。
$ ksh -c 'a=global; f () { typeset a=local; }; f; echo $a'
local
$ ksh -c 'a=global; function f { typeset a=local; }; f; echo $a'
global
kshのもう1つの違いは、function
キーワードを使用して定義された関数に独自のトラップコンテキストがあることです。関数が実行されると、関数の外部で定義されたトラップは無視され、関数内の致命的なエラーはスクリプト全体ではなく関数でのみ終了します。また、$0
で定義された関数の関数名ですが、function
で定義された関数のスクリプト名です()
。
Pdksh は ATT ksh をエミュレートしません。 pdkshではtypeset
機能に関係なくローカルスコープ変数が生成され、ローカルトラップはありません(使用によってはわずかなfunction
違いがありますが、詳細についてはマニュアルページを参照)。
Bashとzshはfunction
ksh互換キーワードを導入します。ただし、これらのシェルでは bash および zsh 拡張と同様に厳密に同じですfunction foo { … }
(上記のように定義を解析する際の潜在的なエイリアス拡張を除く)。キーワードは常にローカル変数を宣言します(もちろん除外)、トラップはローカルではありません(オプションを設定してzshからローカルトラップを取得できます)。foo () { … }
function foo () { … }
typeset
-g
local_traps