Shell

sh 中的函式可以有零語句嗎?

  • March 7, 2017

是否有任何相關標準規定sh必須對空函式執行什麼操作?

以下程式碼段定義了一個帶有零語句的函式

a() {
}

子shell版本似乎被同等對待

a() (
)

ashzsh接受任一構造作為不執行任何操作且退出狀態為零的函式。

ksh( ksh93) 並且bash都將該函式視為語法錯誤而拒絕

$ a() {
> }
ksh: syntax error: `}' unexpected

並與 bash

bash-4.4$ a() {
> }
bash: syntax error near unexpected token `}'

,在符合要求的應用程序中,函式在大括號之間可能沒有空主體。


POSIX將函式定義命令定義為:

fname ( ) compound-command [io-redirect ...]

其中所有這些詞都是規範中其他地方定義的事物的佔位符。compound-command是函式的主體。

複合命令被定義為幾個項目之一,包括循環、條件和案例語句,但在這裡最相關的是分組命令,它在兩種情況下定義

( compound-list )

在子shell環境中執行compound-list;請參閱 Shell 執行環境。影響環境的變數分配和內置命令在列表完成後將不再有效。(…關於算術展開的段落省略了…

{ compound-list ; }

在目前流程環境中執行複合列表。此處顯示的分號是分隔 } 保留字的控制運算符的範例。其他分隔符也是可能的,如 Shell Grammar 所示;<newline> 經常使用。

如果可以為空,則空的{\n}主體將是有效的。compound-list

Shell Grammar反過來定義了 shell 命令語言的解析規則,包括Compound_list

compound_list    : linebreak term
                 | linebreak term separator

這意味著複合列表要麼linebreak後跟 a term,要麼linebreak後跟 aterm和 a separatorseparator;&linebreak是一個可能為空的換行序列。因此,如果term可以為空,則這可以為空。

term是:

term             : term separator and_or
                 |                and_or

and_or

and_or           :                         pipeline
                 | and_or AND_IF linebreak pipeline
                 | and_or OR_IF  linebreak pipeline

最後兩行涵蓋&&||。是由字元分隔pipeline的非空 s 序列。是簡單命令、複合命令或函式定義。如果簡單或複合命令可以為空,那麼, 和, 可以為空。command``|``command``term``command

一個簡單的命令總是包含cmd_namecmd_word或中的一個cmd_prefixcmd_prefix是重定向或分配,可選擇附加到另一個前綴。另外兩個都分解為WORD,語法中的一個標記,它是一個非空的單詞字元序列。所以一個簡單的命令永遠不會是空的。

我們已經看過複合命令了,但這次讓我們從語法的角度回過頭來。複合命令是大括號組、子shell、forwhileuntil循環以及if、 或 a之一case。所有這些都包含一個固定的詞(如“ for”)或至少一個(或。{所以復合命令永遠不會是空的。

因此 acommand永遠不會是空的,所以pipeline永遠不會是空的,也不會and_or,termcompound_list。這意味著

{
}

是不允許的,所以函式定義

a() {
}

也無效。


以上所有內容都適用於符合要求的可移植 shell 腳本。zsh並且ash可以自由地擴展他們的實現來處理他們想要的無效腳本,並且他們選擇的實現似乎是明智和方便的。Bash、ksh、dash 和其他人採取了更簡約的方式來實現所需的內容。所有這些都是一致的選擇。

一個可移植的腳本總是需要提供一個非空的函式體,但是一個單獨針對(比如說)zsh 的腳本不需要。

引用自:https://unix.stackexchange.com/questions/349632