为什么 $foo=* 不会导致错误?

为什么 $foo=* 不会导致错误?

我了解到 shell 扩展了某些类型的字符。这就是为什么在写作时:

$ echo *

我得到目录和文件的列表,假设我得到:

Applications Desktop Documents

现在,假设我写

$ foo=Applications Desktop Documents

我得到:

-bash: Desktop: command not found

很好,但是写的时候:

$ foo=*

那行得通,为什么呢?我确信 * 应该扩展并给出与上面相同的错误。

写作时

$ echo ${#foo}

我得到答案 1,这表明 * 已保存到 foo

为什么 * 没有在作业中扩展?当我写作时它确实会扩展

$ echo ${foo}

谢谢

答案1

变量赋值期间不会发生路径名扩展。以下是 bash 联机帮助页的摘录:

如果未给出值,则为该变量分配空字符串。所有值都会经历波形符扩展、参数和变量扩展、命令替换、算术扩展和引号删除(请参阅下面的扩展)。如果变量设置了整数属性,则即使未使用 $((...)) 扩展,值也会被计算为算术表达式(请参阅下面的算术扩展)。不执行分词,“$@”除外,如下特殊参数中所述。不执行路径名扩展。

当您执行 的赋值时foo=*, foo 变量将包含一个文字*。当您稍后使用变量(不带引号)时,参数首先扩展为文字*,然后发生路径名扩展。您可以*通过引用参数扩展来验证它是否包含文字:

$ foo=*
$ echo "$foo"
*

bash 中此规则有一些例外,例如在分配数组时:

$ foo=(*)

在上面的示例中,路径名扩展立即发生,并且数组包含与 glob 匹配的文件列表。

答案2

如果 shell 无法将通配符扩展为 glob,则按字面处理:

$ cd scratch
$ rm *
$ foo=*
$ echo $foo
*
$ echo "$foo"
*
$ touch file
$ echo $foo
file
$ echo "$foo"
*

相关内容