对于以下两个例子中的每一个,我都会尝试解释我期望的结果和我得到的结果。我希望你帮我理解为什么我错了。
1)
VAR1=VAR2
$VAR1=FOO
结果:-bash: VAR2=FOO: command not found
在第二行中,$VAR1
扩展为VAR2
,但为什么Bash将结果VAR2=FOO
解释为命令名而不是变量赋值?
2)
'VAR=FOO'
结果:-bash: VAR=FOO: command not found
为什么引号使Bash将变量赋值视为命令名?
请您一步一步地描述Bash如何处理我的两个例子?
答案 0 :(得分:5)
在此知识库中的其他Q& A条目中,如何最好地间接分配变量。其中包括:
如果这是您实际打算提出的问题,那么这个问题应该作为副本关闭。我将做出相反的假设并专注于字面问题 - 为什么你的其他方法失败 - 下面。
$var1=foo
或'var=foo'
会失败?POSIX shell command language specification对作业的构成非常具体,如下所述:
4.21 Variable Assignment
在shell命令语言中,由以下部分组成的单词:
varname=value
当在定义分配的上下文中使用时,值(表示单词或字段)应指定为表示的变量的值VARNAME
varname 和 value 部分应分别满足名称和单词的要求,除了它们由嵌入的不带引号的等号分隔,此外其他分隔符。
另外,来自section 2.9.1, on Simple Commands,重点补充:
根据Shell语法规则识别为变量赋值或重定向的单词将保存,以便在步骤3和4中进行处理。
应扩展非变量赋值或重定向的单词。如果任何字段在扩展后仍然存在,则第一个字段应被视为命令名称,其余字段是命令。
重定向应按重定向中所述执行。
- 醇>
在分配值之前,应扩展每个变量赋值以进行波浪扩展,参数扩展,命令替换,算术扩展和引用删除。
另外,从语法:
如果'='前面的所有字符都形成有效名称(请参阅Base Definitions volume of IEEE Std 1003.1-2001, Section 3.230, Name),则应返回令牌ASSIGNMENT_WORD。 (引用的字符不能参与形成有效名称。)
请注意:
$var1=foo
无法充当作业正如语法中所给出的,分配中=
之前的所有字符必须是变量名中的有效字符才能被识别。 $
不是名称中的有效字符。由于在简单命令处理的步骤1中识别分配,在扩展之前,文本文本$var1
,而不是该变量的值,用于此匹配。
'var=foo'
无法充当作业首先,=
之前的所有字符必须在变量名中有效,而'
在变量名中无效。
其次,只有在未引用=
时才会识别作业。
答案 1 :(得分:4)
1)
VAR1=VAR2
$VAR1=FOO
您希望使用变量中包含的变量名来进行赋值。 Bash语法不允许这样做。但是,有一个简单的解决方法:
VAR1=VAR2
declare "$VAR1"=FOO
它也适用于local
和export
。
2)
通过使用单引号(双引号会产生相同的结果),您告诉Bash里面的内容是字符串并将其视为单个实体。由于它是该行的第一个项目,Bash尝试在其PATH中找到别名,shell内置或可执行文件,其名称为VAR = FOO。没找到它,它告诉你没有这样的命令。
分配不是正常命令。要执行引号中包含的赋值,您需要使用eval
,如下所示:
eval "$VAR1=FOO" # But please don't do that in real life
大多数有经验的bash程序员可能会告诉你要避免使用eval
,因为它有严重的缺点,而且我只是为了推荐使用它而作为一个例子:虽然在上面的例子中它不会涉及任何由于VAR1的值已知且安全,因此存在安全风险或错误可能性,在许多情况下,任意(即用户提供的)值可能导致崩溃或意外行为。引用eval
语句也比较困难,降低了可读性。
答案 2 :(得分:-1)
你在程序的早期声明了VAR2,对吧?
如果您尝试将VAR2的值分配给VAR1,那么您需要确保并在VAR2前面使用$,如下所示:
VAR1=$VAR2
这将设置VAR2的值等于VAR1,因为当你使用$时,你说的是存储在变量中的值。否则它不会将其识别为变量。
基本上,在其前面没有$
的变量将被解释为命令。任何一个字都会。这就是为什么我们让$澄清"嘿,这是一个变量"。