Bash - 为什么$ VAR1 = FOO或' VAR = FOO' (带引号)找不到返回命令?

时间:2017-01-20 21:37:00

标签: bash

对于以下两个例子中的每一个,我都会尝试解释我期望的结果和我得到的结果。我希望你帮我理解为什么我错了。

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如何处理我的两个例子?

3 个答案:

答案 0 :(得分:5)

在此知识库中的其他Q& A条目中,如何最好地间接分配变量。其中包括:

如果这是您实际打算提出的问题,那么这个问题应该作为副本关闭。我将做出相反的假设并专注于字面问题 - 为什么你的其他方法失败 - 下面。

POSIX sh语言指定为有效赋值是什么?为什么$var1=foo'var=foo'会失败?

背景:关于POSIX sh规范

POSIX shell command language specification对作业的构成非常具体,如下所述:

  

4.21 Variable Assignment

     

在shell命令语言中,由以下部分组成的单词:

varname=value
     

当在定义分配的上下文中使用时,(表示单词或字段)应指定为表示的变量的值VARNAME

     

varname value 部分应分别满足名称和单词的要求,除了它们由嵌入的不带引号的等号分隔,此外其他分隔符。

另外,来自section 2.9.1, on Simple Commands,重点补充:

  
      
  1. 根据Shell语法规则识别为变量赋值或重定向的单词将保存,以便在步骤3和4中进行处理。

  2.   
  3. 应扩展非变量赋值或重定向的单词。如果任何字段在扩展后仍然存在,则第一个字段应被视为命令名称,其余字段是命令。

  4.   
  5. 重定向应按重定向中所述执行。

  6.   
  7. 在分配值之前,应扩展每个变量赋值以进行波浪扩展,参数扩展,命令替换,算术扩展和引用删除。

  8.   

另外,从语法:

  

如果'='前面的所有字符都形成有效名称(请参阅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

它也适用于localexport

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,因为当你使用$时,你说的是存储在变量中的值。否则它不会将其识别为变量。

基本上,在其前面没有$的变量将被解释为命令。任何一个字都会。这就是为什么我们让$澄清"嘿,这是一个变量"。