Bash

為什麼帶引號的變數中的選項會失敗,但不帶引號時會起作用?

  • January 12, 2019

我讀到我應該在 bash 中引用變數,例如“ $ foo" instead of $ 富。但是,在編寫腳本時,我發現了一個不帶引號但不帶引號的情況:

wget_options='--mirror --no-host-directories'
local_root="$1" # ./testdir recieved from command line
remote_root="$2" # ftp://XXX recieved from command line 
relative_path="$3" # /XXX received from command line

這個有效:

wget $wget_options --directory_prefix="$local_root" "$remote_root$relative_path"

這個沒有(注意 $wget_options 周圍的雙引號):

wget "$wget_options" --directory_prefix="$local_root" "$remote_root$relative_path"
  • 這是什麼原因?
  • 第一行是好版本嗎?還是我應該懷疑某處存在導致這種行為的隱藏錯誤?
  • 一般來說,我在哪裡可以找到好的文件來了解 bash 及其引用的工作原理?在編寫這個腳本的過程中,我覺得我開始在反複試驗的基礎上工作,而不是理解規則。

基本上,您應該雙引號變數擴展以保護它們免於分詞(和文件名生成)。但是,在您的範例中,

wget_options='--mirror --no-host-directories'
wget $wget_options --directory_prefix="$local_root" "$remote_root$relative_path"

分詞正是您想要的。

使用"$wget_options"(引用),wget不知道如何處理單個參數--mirror --no-host-directories並抱怨

wget: unknown option -- mirror --no-host-directories

wget查看這兩個選項--mirror--no-host-directories作為單獨的選項,必須進行分詞。

有更強大的方法可以做到這一點。如果您正在使用bash或任何其他使用數組的 shell bash,請參閱glenn jackman’s answerGilles 的回答還描述了一種更簡單的外殼的替代解決方案,例如標準/bin/sh. 兩者本質上都將每個選項儲存為數組中的單獨元素。

具有良好答案的相關問題:為什麼我的 shell 腳本會因空格或其他特殊字元而窒息?


雙引號變數擴展是一個很好的經驗法則。那樣做。然後請注意極少數情況下您不應該這樣做。這些將通過診斷消息呈現給您,例如上述錯誤消息。

在某些情況下,您不需要引用變數擴展。但是無論如何繼續使用雙引號會更容易,因為它沒有太大區別。一種這樣的情況是

variable=$other_variable

另一個是

case $variable in
   ...) ... ;;
esac

最健壯的編碼方式是使用數組:

wget_options=(
   --mirror 
   --no-host-directories
   --directory_prefix="$1"
)
wget "${wget_options[@]}" "$2/$3"

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