linux bash 中 單引號 與 雙引號


1 不是一回事!

在 bash 中,單引號 ' 與 雙引號 " 具有不同的意義。

簡單的說,

  • 單引號 包裹的內容作變量解析、字符轉義操作,只作為普通純文本原樣輸出。
  • 雙引號 包裹的內容進行變量解析、字符轉義等操作。

參考案例1

參考資料:

  1. bash manual
  2. bash man
  3. bash 舊版本的中文翻譯

2 嵌套特殊需求

執行以下命令,期待打印一段字符串到受保護的文件中

sudo bash -c "echo '#!/bin/sh' >> /usr/local/TEST_FILES"

原本以為會在 /usr/local/TEST_FILES 中寫入以下內容:

#!/bin/sh

而實際情況卻是命令出錯:

bash: !/bin/sh': event not found

為什么會這樣的?

參見這里 的 Event Designators 部分。一個 designator(指示器)表示對歷史命令中的某一項的引用;嘆號 ! 可以作為命令的一部分,其后跟不同的字符表示不同的引用。也就是說 嘆號 后緊接着的不是 (空格)(制表符)(行結束符)=(的話,都可以表示一條命令。()如:

!n      執行第n個命令
!!      執行上一個命令
!STRING 執行最近一次以STRING開頭的命令

## 執行歷史命令
# !!      運行上一條命令
# !88     運行第88條命令
# !ca     運行上一個包含ca的命令

所以出錯原因就是 !/bin/sh' 被解析成了一個命令引用,而幸好沒有執行過的命令中沒有以之開頭的,所以直接報錯而不是直接執行了。

3 解決辦法

既然單引號是不做轉義處理,那么我們把兩種引號的位置互換以下,直接用 單引號包裹命令如何?即:

sudo bash -c 'echo "#!/bin/sh" >> /usr/local/TEST_FILES'

結果表明這是可行的。

當然也有一種不優雅的辦法,就是嵌套單引號, 即:

sudo bash -c $'echo \‘#!/bin/sh\’ >> /usr/local/TEST_FILES'

4 題外話

引號問題依舊很迷,因為,直接輸入以下命令:

echo "#!/bin/sh"

卻依舊是命令出錯:

bash: !/bin/sh“: event not found

這也就是說,在 bash -c STRING 的 字面命令字符 STRING 中 雙引號的行為 與 bash 命令參數中的雙引號 的行為 是不一致的

是否可以總結:

  • 單引號: 字面串
  • 雙引號: 解析串
  • 命令行默認:解析串
a=apple
echo $a             #apple
echo "$a"          #apple
echo '$a'           #$a
echo ‘"$a"’        #"$a"
echo "'$a'"        #'apple'

5 結論

結合討論difference-between-single-quoted-string-and-double-quoted-string以及其中提到的網站

  • "weak quote"
  • 'strong quote'
  • $'C String': 使用 C語言那種轉義規則處理單引號的字符串,得到的結果依舊是被單引號包裹的,即結果字符串是在強引用的作用范圍內。
  • $"I18N String":根據 當前 locale,如果有可用的翻譯,將用翻譯替換雙引號內的字符串,得到的結果依舊是被雙引號包裹的,即結果字符串是在弱引用的作用范圍內。

進一步了解,可以查閱手冊的相關介紹


如需轉載請注明出處!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM