「function foo(){}」と「foo(){}」の違い

「function foo(){}」と「foo(){}」の違い

bash関数を定義するためにキーワードを使用または省略できますfunction。違いはありますか?

#!/bin/bash

function foo() {
  echo "foo"
}

bar() {
  echo "bar"
}

foo

bar

関数への呼び出しはすべてfoo成功し、bar違いは見られません。それで、これが単に可読性のためであるのか、それとも何か抜けたのかどうか疑問に思います。

ただし、他のシェル(dashdebian / 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

functionATT ksh (pdksh や mksh などの子を除く) では、Bourne/POSIX 構文で定義された関数と Bourne/POSIX 構文で定義された関数とにはいくつかの違いがあります。で定義した関数内で、このキーワードfunctiontypesetローカル変数を宣言します。関数が終了すると、この変数の値は関数を開始する前の値にリセットされます。クラシック構文を使用すると、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はfunctionksh互換キーワードを導入します。ただし、これらのシェルでは bash および zsh 拡張と同様に厳密に同じですfunction foo { … }(上記のように定義を解析する際の潜在的なエイリアス拡張を除く)。キーワードは常にローカル変数を宣言します(もちろん除外)、トラップはローカルではありません(オプションを設定してzshからローカルトラップを取得できます)。foo () { … }function foo () { … }typeset-glocal_traps

おすすめ記事