Bash

哪些字元需要在不帶引號的文件中轉義?

  • April 9, 2017

我有基於瀏覽器的 shell/終端,它執行 bash 命令並且我正在轉義空格,但事實證明括號也需要轉義。對於不在引號中的文件名,還需要轉義哪些其他字元?

簡單的解決方案是在開頭放一個單引號 ( '),在結尾放一個單引號,並將'文件名中的每個字元替換為 4 字元序列'\''。所有字元在單引號字元串中都失去了它們的特殊含義,除了'標記字元串結尾的字元本身。該序列'\''結束單引號文字,緊隨其後的是帶引號的單引號,並打開一個新的單引號文字。因此文件名

This file's name has some weird characters!
Will you manage to escape them?

可以引用如下:

somecommand 'This file'\''s name has some weird characters!
Will you manage to escape them?'

雙引號有更複雜的轉義規則,如果啟動歷史替換,則不允許您包含驚嘆號!,因此我不會進一步考慮它們。

另一種方法是使用反斜杠保護字元。這適用於除換行符以外的每個字元;對於換行符,將其放在單引號(或雙引號)內是唯一的解決方案。如果您想最小化反斜杠的數量以向使用者呈現引用的名稱,您可以將其限制在需要反斜杠的地方;但是,您省略的反斜杠越多,您就越有可能忘記需要的反斜杠。字母、數字和非 ASCII 字元總是可以的¹。不確定時引用空格和標點符號。

使用典型的 shell(ksh、bash 或 zsh),至少在某些情況下需要引用以下字元。

  • 空格(空格、製表符、換行符——記住換行符不能用反斜杠引用)。
  • !——歷史擴展。
  • "— 外殼語法。
  • #— 註釋以空格開頭;zsh 萬用字元。
  • $— 外殼語法。
  • &— 外殼語法。
  • ' — 外殼語法。
  • (— 即使在一個單詞的中間:ksh 擴展 glob(也可用於 bash 和 zsh);zsh 萬用字元。
  • )(見(
  • *— sh 萬用字元。
  • ,— 僅在大括號內展開。
  • ;— 外殼語法。
  • <— 外殼語法。
  • =— 在 zsh 中,當它位於文件名的開頭時(使用 PATH 查找的文件名擴展)。
  • >— 外殼語法。
  • ?— sh 萬用字元。
  • [— sh 萬用字元。
  • \— 外殼語法。
  • ]——你可以不引用它而僥倖逃脫。
  • ^— 歷史擴展;zsh 萬用字元。
  • {— 大括號擴展。
  • |— 外殼語法。
  • }— 需要在 zsh 中轉義,當沒有匹配的左大括號時,其他 shell 會更寬鬆。
  • ~— 位於文件名開頭的主目錄擴展;zsh 萬用字元;當它是最後一個字元時總是安全的。

更多字元有時可能需要特殊處理:

  • -對 shell 來說不是特殊的,但是當它位於命令參數的開頭時,它表示一個選項。它不能用引號保護,因為特殊處理在命令中,而不是在 shell 中。要保護以 開頭的文件名-,您可以./在它前面加上 - 這樣它仍然是同一個文件,但參數不再以開頭-
  • .本身並不特殊,但*預設情況下,點文件被排除在 glob 之外。
  • :對 shell 來說不是特殊的,但有些命令會專門解析它,例如指示遠端文件 ( hostname:filename)。請查閱命令的文件以了解如何處理包含冒號的文件名。

¹除非使用者配置了備用歷史擴展字元。一些 shell 允許這樣做。這是使用單引號而不是反斜杠的另一個原因。

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