Bash

為什麼不看 bash -c ‘’echo $RANDOM’’ 列印任何東西?

  • March 29, 2022

我希望此命令每 2 秒在螢幕上列印一個隨機值,但它不會列印任何內容:

watch bash -c '"echo $RANDOM"'

但是,此命令確實每 2 秒列印一個隨機值:

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

顯然我必須轉義美元符號,但我想了解原因,因為在第一種情況下,watch 命令在頂部報告正在正確執行命令:

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

在第二種情況下,它報告正在執行此命令,如預期的那樣:

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

好的,我明白了,必須轉義美元符號才能正確到達 bash 命令。但是,為什麼?watch 命令在執行命令之前對 $RANDOM 做了什麼以使其不輸出任何內容?

就像評論中提到的@steeldriver 一樣,預設情況watch下通過sh -c. 不過,它似乎首先使用空格加入任何參數。

watch bash -c '"echo $RANDOM"'

它獲取 args bash, -c, "echo $RANDOM", 產生bash -c "echo $RANDOM", 並sh使用兩個 args-cbash -c "echo $RANDOM".

然後sh是雙引號內的變數並適當地擴展它。如果您sh不支持 special $RANDOM,則可能未設置整個變數,並且您在那裡得到一個空字元串。然後生成的命令是bash -c "echo ",它啟動 Bash,告訴它只列印一個換行符。

(如果你sh是 Bash 並且確實有$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,它會跳過中間的 shell,這將按照您期望的方式工作,而無需引用地獄:

watch -x bash -c 'echo $RANDOM'

引用自:https://unix.stackexchange.com/questions/697288