2011-07-16 114 views
9

以下是我想說明的一個簡單測試用例。變量擴展在zsh中與bash中的變量不同

在bash,

# define the function f 
f() { ls $args; } 

# Runs the command `ls` 
f 

# Runs the fommand `ls -a` 
args="-a" 
f 

# Runs the command `ls -a -l` 
args="-a -l" 
f 

但zsh中

# define the function f 
f() { ls $args } 

# Runs the command `ls` 
f 

# Runs the fommand `ls -a` 
args="-a" 
f 

# I expect it to run `ls -a -l`, instead it gives me an error 
args="-a -l" 
f 

在上面zsh的最後一行,給了我下面的錯誤

ls: invalid option -- ' ' 
Try `ls --help' for more information. 

我想的zsh正在執行

ls "-a -l" 

這是我得到同樣的錯誤。

那麼,我該如何得到bash的行爲呢?

我不確定我是否清楚,請告訴我是否有您想要知道的事情。

+2

這不回答你的問題,但我認爲這是更好的:'F(){LS 「$ @」; }; f -a -l' –

+0

@glenn,是的,絕對是。正如我所說的,這只是一個更大的問題的例子,我必須使用args變量。 –

+1

@ShrikantSharat如果您正在爲bash和zsh(和ksh)編寫腳本,請不要使用'args'變量來執行此操作。改用數組。 – Gilles

回答

21

區別在於(默認情況下)zsh不針對未加引號的參數展開進行分詞。

您可以通過設置SH_WORD_SPLIT選項或使用=標誌上的單個擴張使「正常」的分詞:

ls ${=args} 

setopt SH_WORD_SPLIT 
ls $args 

如果你的目標炮彈支持陣列( ksh,bash,zsh),那麼你最好使用數組:

args=(-a -l) 
ls "${args[@]}" 

zsh FAQ

zsh Manual

  • 14.3 Parameter Expansion

    請特別注意的事實是沒有引用的參數的話,不會自動上的空白,除非選項SH_WORD_SPLIT設置分割;有關更多詳細信息,請參閱下面對此選項的引用這是與其他shell的重要區別。

  • SH_WORD_SPLIT

    成因場分裂要在不帶引號的參數擴展進行。

+0

是的,那正是我想要的。我不知道該在哪裏尋找或尋找什麼,你能指出一些解釋這個的文檔嗎?感謝你的回答。 –

+0

另外,是否與bash兼容的'$ {= args}'用法?我的測試證實它是... –

+3

* bash *(3.2.48和4.2.10)的所有版本都拒絕'$ {= ...}'。我很確定它是特定於* zsh *。如果你的目標是* bash *和* zsh *,那麼你可以嘗試一個數組(在我更新的答案中)。 –