7

で:

~$ `echo ls`
bin/  Desktop/

しかし、魚では:

fish: Illegal command name “(echo ls)”
~% (echo ls)

(コマンド ラインの上にエラー メッセージが表示されることに注意してください。)

~% echo (echo ls)
ls
~% eval (echo ls)
bin/  Desktop/

fish: Illegal command name “(echo ls)”
exec (echo ls)
     ^
~% exec (echo ls)

コマンド置換は、コマンド自体としてではなく、コマンドのパラメーターとしてのみ機能するようですか? なんで?

まあ、ヘルプドキュメントは言う

パラメーターに一連の括弧が含まれている場合、括弧で囲まれたテキストはコマンドのリストとして解釈されます。

しかし、それでも、なぜですか?

4

2 に答える 2

7

アップデート

この回答は 10 年前の 2010 年に書かれました。fish の最近のバージョン (私は 3.1.2 でテストしました) が更新され、set cmd ls; $cmd現在有効です。

どのように

これは、コマンド置換がパラメーター展開に属し、コマンドとして許可されていないためです。

同様の例:

で:

tmpls=ls
$tmpls

しかし、魚では:

% set cmd ls; $cmd
fish: Variables may not be used as commands.
...

どうして

要するに、検証可能性に優れています

この記事では、詳細について説明します。

通常のシェルでは変数をコマンドとして使用できるため、スクリプトの構文を確実にチェックすることはできません。たとえば、この bash/zsh コードのスニペットは、運次第で合法である場合とそうでない場合があります。ラッキーだと思いますか?

    if true; then if [ $RANDOM -lt 1024 ]; then END=fi; else END=true; fi; $END

bash と zsh はどちらも、ユーザーがリターン キーを押したときに、現在のバッファー内のコマンドが終了したかどうかを判断しようとしますが、このような問題のために失敗することがあります。さらに悪いことに、この完全に合法的なコードは bash によって拒否されます。

  FI=fi; foo() { if true; then true; $FI; }

変数はコマンドとして許可されていないため、Fish はこの種の問題を回避します。コマンドとして変数を使用してできることはすべて、eval コマンドまたは関数を使用して、よりクリーンな方法で実行できます。

同じ理由で、コマンド置換はコマンドとして許可されていません。

(注: 'if' と 'fi' は単純なコマンドではなく予約語であるため、引用された例は公平ではありません。以下のコメントを参照してください。)

于 2010-07-19T15:58:54.907 に答える
0

それは展開の順序と関係があります。

から: help expand-command-substitution_fish

複数のパラメータ展開を組み合わせる場合、展開は次の順序で実行されます。

 * Command substitutions
 * Variable expansions
 * Bracket expansion
 * Pid expansion
 * Wildcard expansion

展開は右から左に実行され、ネストされたブラケット展開は内側と外側から実行されます。

からman bash:

展開の順序は、ブレース展開、チルダ展開、パラメーター、変数と算術展開、およびコマンド置換 (左から右に行われる)、単語分割、およびパス名展開です。

于 2010-07-19T14:02:24.870 に答える