Bash变量赋值时出现“Command not found”错误

704

我有一个名为test.sh的脚本:

#!/bin/bash
STR = "Hello World"
echo $STR

当我运行 sh test.sh 时,我得到了以下输出:

test.sh: line 2: STR: command not found

我做错了什么? 我查看了在线的非常基础/初学者的bash脚本教程,这就是他们声明变量的方式......所以我不确定我做错了什么。

我在Ubuntu Server 9.10上。 是的,bash位于/bin/bash


114
很高兴你提出这个问题,你不是唯一一个不熟悉bash的新手! - miller the gorilla
11
感谢你提出这个问题。这并不是一个令人尴尬的问题。我正在办公室加班到深夜,周围没有Bash专家可以回答这个问题。 - Adway Lele
4
现在(差不多七年后!)有一个名为shellcheck的免费开源代码检查工具,可以自动检测此类和其他常见的语法问题。它可以在线使用,也可以离线安装并集成到您的编辑器中。 - that other guy
请参见 https://dev59.com/Nl8d5IYBdhLWcg3wTQwn - tripleee
我建议你使用 #!/usr/bin/env bash 而不是直接使用 #!/bin/bash,除非你绝对确定你的 bash/bin 中,因为这个答案:https://dev59.com/0GEi5IYBdhLWcg3wIJJH#21613044 - Alejandro Blasco
6个回答

1231

= 符号周围不能有空格。

当你写成这样时:

STR = "foo"

bash尝试以两个参数(字符串“=”和“foo”)运行名为STR的命令。

当您编写以下内容时:

STR =foo

bash试图用一个参数(字符串=foo)来运行名为 STR 的命令。

当你写下以下内容时:

STR= foo

bash尝试在其环境中以STR设置为空字符串运行命令foo

我不确定这是否有助于澄清,还是只是混淆,但请注意:

  1. 第一个命令与以下命令完全等效:STR "=" "foo",
  2. 第二个命令与以下命令相同:STR "=foo",
  3. 最后一个命令等同于STR="" foo

sh语言规范第2.9.1节的相关部分说明:

“简单命令”是一系列可选的变量赋值和重定向,可以以任何顺序出现,后面可以跟单词和重定向,由控制操作符终止。

在这种情况下,word是bash即将运行的命令。 任何包含=(除了在字符串开头的位置之外的任何位置)并且不是重定向,并且其中=之前的部分是有效变量名称的字符串都是变量赋值,而除重定向或变量赋值之外的任何字符串都是命令。 在STR = "foo"中,STR不是变量赋值。


10
如果你的变量名中包含“-”,那么会发生同样的错误。此时的解决方法是将“-”移除。 - chomp
3
根据 http://pubs.opengroup.org/onlinepubs/9699919799/ 中第2.10.10节规则7b,“如果“=”之前的所有字符组成一个有效名称(参见XBD Name),则返回 ASSIGNMENT_WORD 标记。” 转到 http://pubs.opengroup.org/onlinepubs/9699919799/ 第3.231节,我们发现,“在Shell命令语言中,一个单词仅由下划线、数字和来自可移植字符集的字母组成。 名称的第一个字符不是数字。” 因此,单词“FOO-BAR=qux”不是变量赋值,因为“FOO-BAR”不是有效名称。 - William Pursell
2
我正在提供赏金以奖励这个对于初学者来说总是很常见的问题的清晰解释(嗯,还有为了能够更快地找到它,每当我想链接它时:D)。感谢让事情变得如此简单! - fedorqui
1
@fedorqui 谢谢!我并不完全相信这是一个清晰的解释,我经常想知道它是否可以更简单明了。 - William Pursell
2
@Timo $st=$i 并非变量赋值。它扩展为一个字符串,并作为命令执行。看起来你正在尝试执行 eval $st=$i。不要这样做。 - William Pursell
显示剩余4条评论

202

去掉等号周围的空格:

#!/bin/bash 
STR="Hello World" 
echo $STR 

11
这很有趣,因为在Windows批处理文件中,“set foo = bar”也是一个常见的错误——人们会嘲笑批处理语言因此而受到嘲笑;-) - Joey
谢谢@joey。我在编写shell脚本时遇到了问题,我在“=”后面用空格初始化变量。你救了我的一天。 - Lalit Rao
为什么Bash不接受左侧字段中的数字?例如3="Hello World",它会抱怨找不到命令。 - Freedo

11

在交互模式下一切看起来都很好:

$ str="Hello World"
$ echo $str
Hello World

显然(!)如Johannes所说,在=周围不要有任何空格。如果在=周围有任何空格,则在交互模式下会出现以下错误:

未找到命令“str”


3
请注意,原帖中写的是STR = "Hello World",因此这个答案在这里不适用。 - fedorqui
@Arkapravo 交互模式的意义是什么,它与 $ 标记有关吗? - Kasun Siyambalapitiya
@KasunSiyambalapitiya 所说的“交互模式”,是指在实际终端中输入这些命令,而不是在脚本中输入。 - numbermaniac

9

我知道这个问题已经得到了非常高质量的解答。但是简单来说,你不能有空格。

#!/bin/bash
STR = "Hello World"
echo $STR

由于等号周围的空格,代码无法正常运行。如果您运行以下代码:...
#!/bin/bash
STR="Hello World"
echo $STR

它将正常工作。


5
当您定义任何变量时,不需要添加任何额外的空格。
例如:
name = "Stack Overflow"  
// it is not valid, you will get an error saying- "Command not found"

因此,请去除空格:

name="Stack Overflow" 

它会正常运行。


0
补充一下已接受的答案 - 在变量名中使用破折号会导致相同的错误。去掉破折号以消除错误。
STR-STR="Hello World"
bash: STR-STR=Hello World: command not found

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接