sh 中的函式可以有零語句嗎?
是否有任何相關標準規定
sh
必須對空函式執行什麼操作?以下程式碼段定義了一個帶有零語句的函式
a() { }
子shell版本似乎被同等對待
a() ( )
ash
並zsh
接受任一構造作為不執行任何操作且退出狀態為零的函式。
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
後跟 aterm
,要麼linebreak
後跟 aterm
和 aseparator
。separator
是;
或&
。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_name
、cmd_word
或中的一個cmd_prefix
。cmd_prefix
是重定向或分配,可選擇附加到另一個前綴。另外兩個都分解為WORD
,語法中的一個標記,它是一個非空的單詞字元序列。所以一個簡單的命令永遠不會是空的。我們已經看過複合命令了,但這次讓我們從語法的角度回過頭來。複合命令是大括號組、子shell、
for
、while
或until
循環以及if
、 或 a之一case
。所有這些都包含一個固定的詞(如“for
”)或至少一個(
或。{
所以復合命令永遠不會是空的。因此 a
command
永遠不會是空的,所以pipeline
永遠不會是空的,也不會and_or
,term
或compound_list
。這意味著{ }
是不允許的,所以函式定義
a() { }
也無效。
以上所有內容都適用於符合要求的可移植 shell 腳本。
zsh
並且ash
可以自由地擴展他們的實現來處理他們想要的無效腳本,並且他們選擇的實現似乎是明智和方便的。Bash、ksh、dash 和其他人採取了更簡約的方式來實現所需的內容。所有這些都是一致的選擇。一個可移植的腳本總是需要提供一個非空的函式體,但是一個單獨針對(比如說)zsh 的腳本不需要。