if var='value' then in Zsh: これは実際にはセミコロンなしで有効な構文ですか?

if var='value' then in Zsh: これは実際にはセミコロンなしで有効な構文ですか?

次のコードは私が試したZsh 5.8で動作します。セミコロンが抜けたにもかかわらずしかし、これは本当に有効なZsh構文ですか?

#!/bin/zsh
if var='value' then
   echo 'then'
fi

割り当て結果なしparse error near `fi':

#!/bin/zsh
if true then
   echo 'then'
fi

セミコロンを使用した正しい構文:

#!/bin/zsh
if true; then
   echo 'then'
fi

セミコロンのないコードは、sh、Bash、およびKsh 93では正しくありません。

if ... thenZshは、特定の状況で同じ行にセミコロンなしでのみ許可するという事実が混乱しています。条件付き役職の割り当ては特別な場合のようです。ドキュメントにはいつセミコロンが必要なのか正確には記載されていません。 https://zsh.sourceforge.io/Doc/Release/Shell-Grammar.html#index-if-construct

実際に私の興味はKshです。。実際にKsh 93を達成しようとすると、次のエラーが発生しますsyntax error at line ...: `fi' unexpected。しかし、Zshで実行するとemulate kshうまくいきます。私はこれが実際にKshではなくZshであり、実際のKshでは常に間違いであるため、うまくいくと思います。これを確認する正確な文書はありますか?

sh、Ksh、Bash、Zshでの試みとその出力は次のとおりです。 https://bitbucket.org/OPiMedia/hel言語s/src/master/comparative/shell/if_then/

ベストアンサー1

割り当てられたら、コマンドを実行できます。たとえば、

LC_ALL=C grep foo file

rcBourneに似たシェルまたは-likeシェルfishで有効です。そして、inとinを使っ/path/to/grepて実行することを意味します(シェルはシステムが呼び出すすべてのインタフェースの前に配置されます)。grepfoofileargv[]LC_ALL=Cenvp[]execve(file, argv[], envp[])

thenしたがって、パーサーがこのトークンを/構成のキーワードとして受け入れて認識することはまったく驚くべきことではありません。thenこれは、コマンドが必要なすべての場所で必要なためです。iffithen

また、次のことができることがわかります。

if then else (echo foo) fi

同じ理由で。

ただし、文書化されておらず、将来変更される可能性があるため、これに依存しません。

if true thenor にはif echo then明らかに / の引数がありますが、then構造体にはその引数はありません。trueechoifthen

実際には、POSIXではthen(構文的に)キーワードとして認識されることはできません。var='value'sh

POSIXの要件:

var=value keyword

keywordキーワードとして認識されるわけではありませんが、実行されるコマンドの名前であまり役に立ちません。しかし、POSIXシェルキーワードの後に​​コマンド名を指定する人は誰もいません。

たとえば、POSIXには次のものが必要です。

var=value if true

iftrue引数として渡され、var=valueその環境で実行できる場合は、コマンドが実行されます。

$ ln -s /bin/printenv bin/if
$ a=bar bash -c 'if a'
bash: -c: line 1: syntax error: unexpected end of file
$ bash -c 'a=foo if a'
foo
$ zsh -c 'a=foo if a'
zsh:1: parse error near `if'

zshがこの要件に従わない場合(シミュレーションでもsh)、実際に問題が発生する可能性はほとんどありません。私は、誰かがというコマンドを呼び出すことを望むまれな場合には、前にリダイレクトがあるかどうかにかかわらず、コマンドを書いたりキーワードifで誤認したりしない'if'ようにしたいと"if"思います。\ififvar=value

$ a=bar bash -c '"if" a'
bar
$ bash -c 'a=foo "if" a'
foo
$ a=bar zsh -c '"if" a'
bar
$ zsh -c 'a=foo "if" a'
foo

ちなみに、POSIXには以下が必要です。

if true; then if true; then echo x; fi fi

(2つの間に改行やセミコロンがないfi)は奇妙な要件ですが、ksh88が実行するアクション(Bourneシェルから継承されます)を指定するだけです。これはPOSIX仕様が主に基づく実装です。

zshこの要件は尊重されず、最後に追加の単語を追加することはできませんfi

if (true) then (echo x) fiを含むほとんどのシェルで動作しますzshが、IIRC POSIXはこの場合その動作を指定しません。


1 実際に歴史的な逸話として初期Unicesにif。これは Bourne シェルまたは C シェルの前にあり、後で独自のif構成をとりました。その後、これらの構造が重複しているため、削除してください。

おすすめ記事