形似赋值语句的参数

咱们知道,在 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 aliasdeclaretypeset,exportreadonly, and local 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'

果真,被当成普通的参数了。

相关文章
相关标签/搜索