“函式 foo() {}”和“foo() {}”之間的區別
我可以
bash
使用或省略function
關鍵字來定義函式。有什麼區別嗎?#!/bin/bash function foo() { echo "foo" } bar() { echo "bar" } foo bar
兩個函式呼叫都
foo
成功了bar
,我看不出有什麼區別。所以我想知道這是否只是為了提高可讀性,還是我缺少一些東西……順便說一句,在其他 shell 中,例如
dash
(在 debian/ubuntu/bin/sh
中符號連結到),使用關鍵字dash
時它會失敗。function
除了第二個版本更便攜之外,AFAIK 沒有任何區別。
有兩種不同語法的原因是歷史原因。
function
關鍵字來自ksh。受 C 啟發的()
語法來自Bourne shell。POSIX僅標準化 Bournefoo ()
語法。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
在 ATT ksh(但不是 pdksh 及其後代,例如 mksh)中,由
function
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 的另一個區別是使用關鍵字定義的函式
function
有自己的陷阱上下文。函式外部定義的陷阱在執行函式時會被忽略,函式內部的致命錯誤僅退出函式而不是整個腳本。此外,$0
是由 定義的函式中的函式名稱,function
但由 定義的函式中的腳本名稱()
。Pdksh 不模擬 ATT ksh。在 pdksh 中,
typeset
無論函式如何,都會創建局部範圍的變數,並且沒有局部陷阱(儘管 usingfunction
確實會產生一些細微的差異 - 有關詳細資訊,請參閱手冊頁)。Bash 和 zsh 引入了
function
與 ksh 兼容的關鍵字。然而,在這些 shell中function foo { … }
,foo () { … }
它們是完全相同的,bash 和 zsh 擴展也是如此function foo () { … }
(解析定義時可能存在的別名擴展除外,如上所述)。typeset
關鍵字總是聲明局部變數(當然with除外)-g
,並且陷阱不是本地的(可以通過設置local_traps
選項在zsh中獲取局部陷阱)。