bash脚本中没有空间的变量赋值背后的原理是什么

时间:2019-07-06 02:52:09

标签: bash shell

我正在尝试为AWS编写一个自动化流程,该流程需要在bash脚本中进行一些JSON处理和其他操作。我关注了一些bash脚本博客,发现了这一点:

<a class="nav-link text-white" [routerLink]='["/another/link/to/component"]' routerLinkActive="aLink">Component 2</a

,带有以下注释:

  

等号(=)的两边都没有空格。我们   还可以从变量名称的开头删除$符号,当   设置

这很丑陋,很难读取,并且与其他脚本语言相比也很困难,在编写bash脚本时,用户很容易通过在两者之间留有空格来犯错。我认为每个人都喜欢编写干净且可读的代码,这种限制肯定不利于代码的可读性。

你能解释为什么吗?带有示例的解释受到高度赞赏。

4 个答案:

答案 0 :(得分:4)

这是因为否则语法将不明确。考虑以下命令行:

cat = foo

是对变量cat的赋值,还是使用参数“ =”和“ foo”运行命令cat?请注意,“ =”和“ foo”都是完全合法的文件名,因此可以在cat上运行。 Shell语法通过命令解释来解决此问题,因此要避免这种解释,您需要省略空格。 cat =foo有同样的问题。

另一方面,请考虑:

var= cat

命令cat是否将变量var设置为空字符串(即var='' cat的简写)或对外壳变量var的赋值运行?同样,shell语法有利于命令解释,因此您需要避免添加空格的诱惑。

shell语法中有很多地方,空格是重要的分隔符。另一个常见的问题是在测试中,如果您在以下位置遗漏了任何

if [ "$foo" = "$bar" ]

...这将导致不同的含义,这可能会导致错误或只是默默地做错了事。

我要说的是shell语法不允许您随意添加或删除空格以提高可读性。甚至不要尝试,您只会破坏事情。

答案 1 :(得分:4)

您需要了解的是Shell语言和语法很旧。真的很老带有变量的UNIX shell的第一个版本是Bourne shell,它是在1977年设计和实现的。那时,很少有先例。 (AFAIK,只是Thompson shell,根据手册的内容,该词不支持变量。)

1970年代设计决策的基本原理...在时间的迷雾中迷失了。由Steve Bourne及其同事在Bell Labs的v6 UNIX上做出设计决定。他们可能不知道40多年后他们的决定仍然有用。

与使用C语言编写程序的替代方法相比,Bourne shell被设计为通用且易于使用。从这些方面来说,这是一次了不起的成功。

但是,任何一种成功的语言都有被广泛采用的“问题”。这就使解决可能出现的任何问题(实际问题或感知问题)变得更加困难。任何更改语言的建议都必须与该更改对语言的现有用户/使用的影响进行权衡。您不想破坏现有程序或脚本。

不管是否在外壳变量分配中允许在=周围加空格,更改此设置都会破坏数百万个外壳脚本。只是不会发生。

当然,Linux(及其之前的UNIX)允许您设计和实现自己的shell。从理论上讲,您可以替换默认外壳。这只是很多工作。

没有什么可以阻止您使用其他脚本语言(例如Python,Ruby,Perl等)编写脚本或设计和实现自己的脚本语言。


总结:

我们不能肯定地知道 为什么他们使用这种语法为变量赋值来设计shell,但是无论如何这都是没有意义的。


参考:

答案 2 :(得分:3)

在许多情况下,它可以防止歧义。否则,如果您有一条语句foo = bar,则可能意味着将foo=作为参数运行bar程序,或设置foo变量到bar。当您不需要空格时,现在您就可以将模糊性限制在程序名称包含等号的情况下,这基本上是闻所未闻的。

答案 3 :(得分:1)

我同意@StephenC,以下是有关消息来源的更多信息:

1975年的Unix v6没有环境,只有一个exec syscall接受了一个程序和一串参数数组。由汤普森(Thompson)编写的系统sh不支持only single digit numbered arguments之类的变量,$1(也许$12至今被解释为${1}2的原因)

自1979年以来,Unix v7受到硬件进步的鼓舞,在exec调用中增加了许多功能,包括a second string arrayman page这样描述,直到今天仍然如此:

  

当进程开始时,exec(2)使称为environment的字符串数组可用。按照惯例,这些字符串的格式为name=value

现在由伯恩(Bourne)编写的系统sh与v6 shell十分相似,但是现在允许您在命令前面以相同格式指定这些环境字符串(因为您将使用哪种其他格式?)。简单化的解析器实质上是将单词分隔成空格,如果包含=并且所有前面的字符都是字母数字,则flagged a word as destined for a variable会被分隔。

由于Unix v7的不可思议的普及性,fork和clones复制了很多东西,包括这种行为,而这就是我们今天仍然看到的。