sh
実装が空の関数で実行する必要があることを指定する関連標準がありますか?
次のコードスニペットは、ステートメントのない関数を定義します。
a() {
}
サブシェルのバージョンも同じように扱われているようです。
a() (
)
ash
zsh
何もせずに終了ステータスがゼロの関数ですべての設定を許可します。
ksh
(ksh93
)と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
またはlinebreak
aterm
とaが続きますseparator
。separator
Is;
または&
。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
|
command
term
command
cmd_name
単純コマンドには常にcmd_word
、またはいずれかが含まれますcmd_prefix
。cmd_prefix
オプションで、別のプレフィックスに追加されるリダイレクトまたは割り当て。残りの2つは、両方ともWORD
単語文字の空でないシーケンスである文法のトークンとして識別されます。したがって、単純なコマンドは決して空ではありません。
複合コマンドについてはすでに見てきましたが、今回は構文の観点から検討してみましょう。複合コマンドは、中かっこグループ、サブシェル、for
ループwhile
、until
またはif
いずれかですcase
。これらのすべてには、少なくとも固定語(「for
」など)または(
orが含まれています。{
したがって、複合コマンドは決して空ではありません。
したがって、aは決してcommand
空にすることはできず、したがって決して空にすることはpipeline
できません、nor and_or
、term
またはcompound_list
。これは意味する
{
}
許可されていないため、関数定義
a() {
}
また、無効です。
上記のすべては、一貫して移植可能なシェルスクリプトに適用されます。無効なスクリプトを処理するために実装を自由に拡張できzsh
、ash
それらが選択した実装は合理的で便利です。 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 (){
:
}