bash 中單引號與雙引號的行為差異

最近在串 ci/cd 的時候發現了一個很細微但我卻忽略的問題,就是 bash 中單引號與雙引號的行為差異。首先看到第一個例子,遠端 ssh 在一台 VM 上下如下指令,這條指令很直覺的就會想到在遠端機器給定FOO 環境變數並且印出吧?

1
$ ssh mark.chang@35.189.166.130 "export FOO=GGININDER; echo $FOO"

但在執行的時候實則不然!FOO 怎麼是空的呢?原因在於這裏 bash 中雙引號會自動解析本來上下文的環境變數,導致這邊印出來的FOO其實是 local 這邊的上下文的環境變數,因為在 local 並沒有設定FOO 所以就是空的了。

1
$

因此要達到預期在遠端 VM 透過 ssh 指令下環境變數並印出,就必須把原來 bash 的雙引號改成用單引號,才不會遇到特殊字元$就自動解析成本來上下文的變數了。

1
$ ssh mark.chang@35.189.166.130 'export FOO=GGININDER; echo $FOO'

改成單引號後,FOO也正確的指向遠端 VM 的環境變數了。

1
$ GGININDER

這裡也延伸出另一個應用,就是如何透過 ssh 將本地的變數指派給遠端 VM 上的變數呢?這時就可以透過單引號與雙引號連用來達到。在單引號中,本地的變數可以透過在前後加入雙引號來指向。

1
2
$ export FOO=1234
ssh mark.chang@35.189.166.130 'export FOO='"$FOO"'; echo $FOO'

如此就可以把本地的變數給指派給遠端 VM 上了。

1
$ 1234

reference:

  1. https://stackoverflow.com/questions/6697753/difference-between-single-and-double-quotes-in-bash