bash 脚本:使用空格

bash 脚本:使用空格

我尝试过网络搜索和该网站上的搜索,但只发现 bash 中字符串使用空格的问题。不过,我想了解 bash 脚本中使用空格背后的一般逻辑,以便我可以更好地记住正确的用法:哪里是强制性的,哪里相反。

几个例子:强制[ $i == b ],相反var1="foo"

答案1

不过我想了解 bash 脚本中使用空格背后的一般逻辑

在分隔命令参数和分隔命令时必须使用空格关键词(或保留字,取决于来源)。这些 是{,,,,,,,,等等。}!iffordodone

周围的空白不是强制的运营商。这些至少是语句终止符;&;条件运算符&&||;所有重定向运算符等><<以及括号()。重定向运算符前面的可选文件描述符编号不能用空格分隔,但运算符周围的额外空格通常并不重要。

所以,这些都很好:

true;true
cat<<file
true&&false
tac|rev
f()(echo foo)

这些不是:

if !somecmd; then ...
f(){echo foo}

第一个将查找命令!somecmd,而不是运行somecmd并反转退出状态。第二个不起作用,因为关键字 '{' 和}必须是单独的单词,并且它们仅在命令开头被识别。它可能是例如f(){ echo foo;}

如果 course 不能作为if语句,因为如果if从单词的开头选择 ,则调用的程序ifconfig将很难使用:

ifsomecmd;then ...

(尽管这一点可能是显而易见的,除非您习惯使用 Fortran。)

那么,你怎么知道这(是一个运算符而{不是一个运算符呢?你通过死记硬背来学习它。这种差异可能是由于历史原因造成的,很多事情都是如此。看:为什么 POSIX Shell Grammar 中的大括号命令组在左大括号后需要空格?

该问题的答案有更多关于运算符和关键字的讨论,并附有参考文献,因此请阅读它们。


不过,以上内容都不能真正帮助您区分作业foo=bar和测试之间的区别[ "$foo" = bar ]

这里的关键是,[就像常规命令一样,它将其运算符和操作数作为不同的参数,并且不会真正查看它们的内部。就像ls -l /somedirectory需要空格来分隔其参数(-l/somedirectory)一样, 也是如此[这对括号不是 shell 语法的一部分(或语法),并且 也不是=,与大多数实际编程语言中的等效构造不同。

至于任务,他们有点棘手。赋值不需要单独出现在命令行上(它们可以与命令一起使用),并且一行上可以有多个赋值。就像这样:

$ foobar=123 foofoo=456 env|grep foo
foofoo=456
foobar=123

它的工作方式(大致)是,shell 将命令拆分为单词(上面的单词是foobar=123,foofoo=456env),并查看最初的单词,看看它们是否看起来像赋值。这两个确实如此,但在这里,没有赋值,只是一个普通的参数echo

$ echo foo=bar
foo=bar

我想 shell 语法在这方面可能有所不同,但是支持这样的事情,即有两个赋值和一个没有参数的命令可能看起来很奇怪(好吧,除非你习惯了 Lua):

foobar = 123 foofoo = 456 env

答案2

关键是空格分隔,除非引用,并且是你必须考虑的:

基本上,shell 执行以下操作:

  1. 读取其输入[...]
  2. 将输入分解为单词和运算符,遵循中描述的引用规则引用。这些标记由元字符分隔。 [...]
  3. 将标记解析为简单命令和复合命令(请参阅外壳命令)。

-3.1.1 外壳操作

和:

简单命令是最常遇到的命令。它只是一系列由空格分隔的单词,由 shell 的控制运算符之一终止[.] -3.2.1 简单命令

和:

  1. 解析器标记为变量赋值(命令名前面的词)和重定向的词被保存以供稍后处理。
  2. 不是变量赋值或重定向的单词被扩展[...]。如果扩展后仍有任何单词,则第一个单词将被视为命令名称,其余单词将被视为参数。

-3.7.1 简单命令扩展

请注意它是如何表述“标记为变量赋值的单词[...]”。因此变量赋值必须是单个单词,因此以下是只是变量赋值:

  • var=value
  • var=" value"

但以下情况则不然:

  • var= value✗(两个词:变量赋值var=- 赋值空字符串 - for 命令value
  • var =value✗(两个词:var带参数的命令=value
  • var" =value"✗(一个字:但变量名不能加引号,所以这是名为 的命令var =value
  • "var=value"✗(一个字:但变量名不能加引号,所以这是名为 的命令var=value

现在 for [ var = value ],[是一个命令(与 相同的命令test),它期望测试和测试的操作数为单独的论点。这样,您可以执行诸如[ "$var" = "$value" ]or 之类的操作test "$var" = "$value",其中,例如,var="a = b"andvalue="b = c"可以包含看起来像测试的内容,但实际上并非如此,因为每个都是单个参数。

因为参数必须是单独的单词,所以 周围需要空格=。这也是为什么"$var"and"$value"必须被引用的原因,否则 shell 会将它们分成单独的单词,并且[会失败。

相关内容