咱們知道,在 Bash 中,當變量出如今一個賦值語句的右側時,變量只會展開,不會分詞,即使變量兩邊沒有引號: 面試
$ foo="1 2"app $ bar=$foo # 不會被拆分紅 bar=1 和 2 兩個詞函數 $ echo "$bar"ui 1 2spa |
可是,當一個形似賦值語句的詞,做爲參數傳給一個命令時,這時分詞步驟就不會少了:code
$ foo="1 2"blog $ printf '%s\n' bar=$fooit bar=1table 2class |
bar=$foo 雖然看起來像是賦值語句,但由於它出如今了命令名稱的後面,因此它就是個普通的參數。它會先展開成 bar=1 2,而後被拆分紅 bar=1 和 2 兩個參數傳給 printf。外部命令也同樣:
$ valueOfa="1 b=2" $ env -i a=$valueOfa env # 你覺得傳給 env 的第二個參數是 "a=1 b=2",但實際上是 "a=1" 和 "b=2" 兩個參數 a=1 b=2 |
但是,有一些命令倒是特殊的,好比 alias:
$ valueOfa="1 b=2" $ alias a=$valueOfa # 傳給 alias 命令的會是 "a=1" 和 "b=2" 兩個參數? $ alias alias a='1 b=2' # 並非,valueOfa 這個變量竟然沒有被分詞! |
像 alias 這樣的內部命令一共有 6 個,分別是:alias、declare、typeset、export、readonly、local,它們的功能都是聲明一個什麼東西,變量或者別名。Bash 對它們的參數作了特殊對待,若是知足賦值語句的格式,則不對其中的變量進行分詞。固然你也能夠就把它們當作是賦值語句,反正賦值語句的效果是建立一個變量,這些參數的效果也是建立一個變量(除了 alias 命令)。Bash 手冊也直接把它們說成是賦值語句:
Assignment statements may also appear as arguments to the
alias
,declare
,typeset
,export
,readonly
, andlocal
builtin commands.
在 Bash 的實現裏,是專門用一個函數對這樣的參數作了特殊處理:
/* This is a hack to suppress word splitting for assignment statements given as arguments to builtins with the ASSIGNMENT_BUILTIN flag set. */ static void fix_assignment_words (words) WORD_LIST *words; {
...
等等,還沒完。上面說,若是知足賦值語句的格式,這些參數纔會被特殊對待,那若是不知足呢?
咱們知道,賦值語句的左邊必須是合法的標識符,合法的標識符得符合「字母下劃線開頭後跟若干個字母數字下劃線」。這樣的話 1=$foo 就一定不是個合法的賦值語句了,下面試一把:
$ foo="1 2=2" $ alias 1=$foo $ alias alias 1='1' alias 2='2' |
果真,被當成普通的參數了。