为啥变量赋值中的空格会在 Bash 中出错? [复制]

Posted

技术标签:

【中文标题】为啥变量赋值中的空格会在 Bash 中出错? [复制]【英文标题】:Why does a space in a variable assignment give an error in Bash? [duplicate]为什么变量赋值中的空格会在 Bash 中出错? [复制] 【发布时间】:2017-06-04 13:06:24 【问题描述】:
#!/bin/bash

declare -r NUM1=5
NUM2 =4                # Line 4

num3=$((NUM1 + NUM2))
num4=$((NUM1 - NUM2))
num5=$((NUM1 * NUM2))
num6=$((NUM1 / NUM2))  # Line 9

echo "$num3"
echo $((5**2))
echo $((5%4)) 

我正在使用这个 bash 脚本,当我运行该脚本时,我得到了错误

./bash_help 
./bash_help: line 4: NUM2: command not found
./bash_help: line 9: NUM1 / NUM2: division by 0 (error token is "NUM2")
5
25
1

所以我把代码改成了这个,错误就消失了。

#!/bin/bash

declare -r NUM1=5
NUM2=4

num3=$((NUM1 + NUM2))
num4=$((NUM1 - NUM2))
num5=$((NUM1 * NUM2))
num6=$((NUM1 / NUM2))

echo "$num3"
echo $((5**2))
echo $((5%4)) 

为什么在给变量赋值时不能使用空格?使用空格来提高代码的可读性是惯例。谁能解释一下?

【问题讨论】:

这只是bash中的范式之一,你不能质疑它 在 shell 中,空格是重要的分隔符。在大多数情况下,您不能添加或删除它们以使事情看起来更好,因为它们会改变命令行的含义。 谢谢,虽然这是一个小问题。清晰可以减少错误。 清晰性和向后兼容性很少同时存在。 POSIX sh 于 1991 年首次发布,其根源可以追溯到 1970 年代。正如 Common LISP 是由历史 LISP 拼凑而成的丑陋且非常有用的庞然大物,Scheme 又小又漂亮,而且完全缺乏实用的库生态系统,bash 处于这种鸿沟的前者(旧的、丑陋的和有用的)方面。 顺便说一句,shellcheck.net 会自动为您捕获此类错误;非常值得使用(就此而言,可以在本地安装它,并让您的编辑器在您工作时自动运行它)。 【参考方案1】:

这不是 bash(或更一般地说,POSIX 系列 shell)中的约定。

至于“为什么”,那是因为各种做错的方式都具有作为命令的有效含义。如果您将NUM2 = 4 赋值为赋值,那么您不能在不引用它的情况下将= 作为文字参数传递。 因此,任何此类更改都将是向后不兼容的,而不是放置在未定义的空间中(POSIX sh 标准的扩展需要存在以避免违反该标准)。

NUM2= 4 # runs "4" as a command, with the environment variable NUM2 set to an empty string
NUM2 =4 # runs "NUM2" as a command, with "=4" as its argument
NUM2 = 4 # runs "NUM2" as a command, with "=" as its first argument, and "4" as another

【讨论】:

【参考方案2】:

在 Bash 中,函数以空格分隔的单词的形式传递参数。

来自文档

“每个运算符和操作数必须是单独的参数。”

变量赋值不同,使用这种语法name=[value]

您不能在等号周围放置不带引号的空格的原因是 bash 会将其解释为命令。

【讨论】:

【参考方案3】:

原因很简单,shell 就是这样设计的。对于具有其他编程语言经验的人来说,这可能没有意义(如果您将 shell 语法称为“语言”,在某种意义上它确实如此)。

Shell 脚本在许多情况下可以简单地不引用字符串(只要作为单个字符串的字符序列不包含任何空格或特殊字符)。多亏了这一点,你可以写:

 my_command -n -X arg1 arg2

而不是(在某种虚构的伪代码中)

 "my_command" "-n" "-X" "arg1" "arg2"

在大多数语言中,情况正好相反:引用文字字符串,从而释放“语法空间”以使用不带任何特殊字符的变量(如 shell 脚本中的 $)。

Shell 语法在常见情况下提供了便利,但代价是在做一些其他事情时不太方便(和可读性)。这既是诅咒,也是祝福。好消息是如果你有一个交互式 shell,你可以 100% 确定你有一个解释器来处理某种(可能是不优雅的)程序。由于其普遍可用性(尽管存在各种不同的风格),shell 是一种非常有用的平台,值得学习。

【讨论】:

以上是关于为啥变量赋值中的空格会在 Bash 中出错? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

shell中$1赋值给变量,此变量却是空的,为啥?

case语句中的变量赋值(bash)[重复]

关于ArrayBuffer和类型化数组的概念

(=)符号后有空格的变量赋值?

为啥我的 bash 脚本无法识别 date 命令中的变量?

Bash 在第一个空格后结束变量?