shの関数に0個のステートメントがありますか?

shの関数に0個のステートメントがありますか?

sh実装が空の関数で実行する必要があることを指定する関連標準がありますか?

次のコードスニペットは、ステートメントのない関数を定義します。

a() {
}

サブシェルのバージョンも同じように扱われているようです。

a() (
)

ashzsh何もせずに終了ステータスがゼロの関数ですべての設定を許可します。

kshksh93)とbash両方の構文エラーで関数を拒否します。

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

そしてバッシュ

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

答え1

いいえ適切なアプリケーションでは、関数の中括弧の間に空の関数本体を含めることはできません。


POSIX機能定義 コマンド定義ように:

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

これらの単語はすべて、仕様の他の場所で定義された項目のプレースホルダーです。compound-command関数の本体です。

複合コマンド次のように定義されます。ループ、条件文、ケース文を含むいくつかの項目のうちの1つですが、ここで最も関連性の高い項目は次のとおりです。グループ化コマンド、2つのケースとして定義:

( compound-list )

サブシェル環境で複合リストを実行します。シェル実行環境をご覧ください。環境に影響を与える変数割り当ておよび組み込みコマンドは、リストの最後まで残してはいけません。 (...算術拡張に関する段落は省略されました...)

{ compound-list ; }

現在のプロセスのコンテキストで化合物リストを実行します。ここに示されているセミコロンは、}予約語を区切る制御演算子の例です。シェル構文に示すように、他の区切り文字も可能です。 <newline>がよく使われます。

空の場合は空の{\n}本文が有効です。compound-list

これシェル構文これは、以下を含むシェルコマンド言語の解析規則をさらに定義します。化合物一覧:

compound_list    : linebreak term
                 | linebreak term separator

つまり、化合物リストlinebreakの後にはatermまたはlinebreakatermとaが続きますseparatorseparatorIs;または&linebreakは空の改行シーケンスです。したがって、nullになることができればnullになる可能性があります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

最後の2行は&&合計をカバーしています||。文字で区切られた空でないsシーケンスpipeline。単純なコマンド、複合コマンド、または機能定義です。したがって、単純コマンドや複合コマンドが null になることができる場合、および null になることができます。command|commandtermcommand

cmd_name単純コマンドには常にcmd_word、またはいずれかが含まれますcmd_prefixcmd_prefixオプションで、別のプレフィックスに追加されるリダイレクトまたは割り当て。残りの2つは、両方ともWORD単語文字の空でないシーケンスである文法のトークンとして識別されます。したがって、単純なコマンドは決して空ではありません。

複合コマンドについてはすでに見てきましたが、今回は構文の観点から検討してみましょう。複合コマンドは、中かっこグループ、サブシェル、forループwhileuntilまたはifいずれかですcase。これらのすべてには、少なくとも固定語(「for」など)または(orが含まれています。{したがって、複合コマンドは決して空ではありません。

したがって、aは決してcommand空にすることはできず、したがって決して空にすることはpipelineできません、nor and_ortermまたはcompound_list。これは意味する

{
}

許可されていないため、関数定義

a() {
}

また、無効です。


上記のすべては、一貫して移植可能なシェルスクリプトに適用されます。無効なスクリプトを処理するために実装を自由に拡張できzshashそれらが選択した実装は合理的で便利です。 Bash、ksh、dash、その他のツールは、必要な機能を達成するためのよりミニマリストなパスを取ります。みんな全会一致の選択でした。

移植可能なスクリプトは常に空ではない関数の本文を提供する必要がありますが(たとえば)zshのみを対象とするスクリプトはそうではありません。

答え2

さまざまなシェルの構文ツリーに興味があるようです。 bashの関連部分は次のとおりです。https://www.gnu.org/software/bash/manual/bashref.html#Shell-Syntax

関数は次のように定義されます。1]:

次の構文を使用して関数を宣言します。
name () compound-command [ redirections ]
または
function name [()] compound-command [ redirections ]

興味のある部分は、次のいずれかである可能性compound-commandがあります。2]:

•ループ構成:繰り返し操作のためのシェルコマンド。
•条件付き構造:条件付き実行に使用されるシェルコマンド。
•コマンドのグループ化:コマンドをグループ化する方法。

{}構文()はacommand groupingで、次のいずれかです。サム]:

( list )
{ list; }

A はlist次のように定義されます。4]:

‘;’リストは、演算子、またはいずれ‘&’かで区切られ、オプションで、‘&&’または‘||’改行文字のいずれかで終わる1つ以上のパイプシーケンスです。‘;’‘&’

A はpipline次のように定義されます。5]:

パイプは、制御演算子またはで‘|’区切られた1つ以上のコマンドシーケンスです‘|&’

関数の例には、1つ以上のコマンドを含める必要がある複合コマンドが含まれており、pipelines各コマンドには1つ以上のコマンドが含まれていますcommands

したがって、Bashでは関数に少なくとも1つのコマンドが必要です。他のシェルも同様であり、構文ガイドを使用できます。

何らかの理由で何もしない関数が必要な場合は、Bashに組み込まれたプレースホルダを使用できます。つまり、:何も成功しません。

a(){:}

答え3

これはbashが得ることができるものの最も近いものです:

a (){  
  :   
}

関連情報