Bash

別名的單引號內的命令替換

  • January 8, 2020

bash 中需要雙引號來進行命令替換:

$ echo "$(date)"
Fri Oct 28 19:16:40 EDT 2016

而單引號不做命令替換:

$ echo '$(date)'
$(date)

…為什麼我會看到以下行為alias似乎表明命令替換是用單引號發生的?

alias d='$(date)'
$ d
No command 'Fri' found, did you mean:
  ....

單引號與雙引號版本

讓我們使用單引號定義別名:

$ alias d='$(date)'

現在,讓我們檢索別名的定義:

$ alias d
alias d='$(date)'

觀察到尚未執行命令替換。

讓我們做同樣的事情,但這次使用雙引號:

$ alias d="$(date)"
$ alias d
alias d='Fri Oct 28 17:01:12 PDT 2016'

因為使用了雙引號,所以在定義別名之前執行了命令替換。

單引號版本

讓我們嘗試執行單引號版本:

$ alias d='$(date)'
$ d
bash: Fri: command not found

單引號版本相當於執行:

$ $(date)
bash: Fri: command not found

在這兩種情況下,執行命令時都會執行命令替換。

變種

讓我們考慮這個使用命令替換並使用單引號定義的別名:

$ alias e='echo $(date)'
$ e
Fri Oct 28 17:05:29 PDT 2016
$ e
Fri Oct 28 17:05:35 PDT 2016

每次我們執行此命令時,date都會再次評估。使用單引號,命令替換是在執行別名時執行的,而不是在定義別名時執行的。

如果在定義別名時使用雙引號,則參數擴展發生在別名定義時。

例如:

$ pwd
/tmp
$ echo $PWD
/tmp
$ alias p="echo $PWD"
$ p
/tmp
$ cd /
$ pwd
/
$ p
/tmp
$ alias p
alias p='echo /tmp'
$ 

如果您希望在呼叫別名時發生參數擴展,請在定義別名時使用單引號:

$ alias p='echo $PWD'
$ p
/tmp
$ cd /
$ p
/
$ 

當然,沒有任何理由執行該命令~~echo "$(date)"~~。我知道您只是將其用作範例,但是由於我已經多次“在野外”看到這種情況,所以無論如何我都會澄清一下:這意味著,執行date命令並擷取輸出(去掉任何尾隨的換行符)。然後將擷取的輸出作為參數傳遞給echo命令,該命令將列印它,以及一個尾隨換行符。與直接執行相比沒有任何優勢date

但是,您在這裡也遇到了不同的問題:

當你設置 aliasd='$(date)'時,當你輸入時,你會得到在命令行d輸入的文字結果——命令將被執行,輸出被擷取,尾隨換行符將被剝離,然後輸出將被解析為命令shell(包括分詞和文件全域擴展)。$(date)``date

由於是星期五,輸出的第一個單詞date是“Fri”,因此 shell 嘗試將其作為命令執行。

如果您想要在鍵入時查看d日期,只需使用:

alias d=date

或者

alias d='date'

或者

alias d="date"

您使用哪種形式並不重要,因為沒有特殊字元需要任何形式的引用。

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