bash -c '"echo $RANDOM"'が何も印刷しないのはなぜですか?

bash -c '"echo $RANDOM"'が何も印刷しないのはなぜですか?

このコマンドを使用して、2秒ごとに画面にランダムな値を印刷したいが、何も印刷されません。

watch bash -c '"echo $RANDOM"'

ただし、このコマンドは2秒ごとにランダムな値を出力します。

watch bash -c '"echo \$RANDOM"'

明らかにドル記号を避けるべきですが、その理由を知りたいです。最初のケースでは、watchコマンドはコマンドが正しく実行されていることを一番上に報告するためです。

Every 2.0s: bash -c "echo $RANDOM"

2番目のケースでは、予想どおりこのコマンドが実行されていることを報告します。

Every 2.0s: bash -c "echo \$RANDOM"

わかりました。 bashコマンドに正しく到達するには、ドル記号をエスケープする必要があります。しかし、なぜまだ? watchコマンドは、コマンドを実行する前に何も出力しないように$RANDOMに対して何をしますか?

答え1

コメントに記載されている@steeldriverと同様に、watchデフォルトでコマンドを実行してsh -c。しかし、最初にスペースで取得したすべての引数を連結するようです。

そして

watch bash -c '"echo $RANDOM"'

bashargs、、、、-c"echo $RANDOM"取り、両方のargsで実行されますbash -c "echo $RANDOM"sh-cbash -c "echo $RANDOM"

次に、sh二重引用符内の変数を適切に拡張します。sh特別な項目がサポートされていない場合、変数全体が設定されず、空の文字$RANDOM列が表示されます。その後、生成されたコマンドはbash -c "echo "Bashを起動し、改行のみを印刷するように指示します。

(もしあなたがshBashであり、それを持っているならば$RANDOM、それを使用するだけですwatch 'echo $RANDOM'。)

シェル(sh)が見える場所にバックスラッシュを追加すると、拡張されず、... "echo \$RANDOM"バックスラッシュのみが削除されます。内部シェル(bash)はecho $RANDOM変数自体を見て拡張します。一重引用符を使用してシェルをgetでソートする場合も同様です... 'echo $RANDOM'

次の中間シェルの拡張を見ることができます(印刷でなければなりませんout)。

export foo=out; watch 'bash -c "foo=in; echo $foo"'

中間シェルをスキップするを使用するwatch -xと、引用符なしで期待どおりに動作します。

watch -x bash -c 'echo $RANDOM'

答え2

~からマニュアルページ:

コマンドには「sh -c」が与えられました...

代わりにecho $RANDOMusingを使用すると、使用できますが、使用できないため出力を取得できません。shbash$RANDOMbashsh

関連情報