为什么元字符周围有时需要空格?

spy*_*don 541 syntax bash shell syntax-error

几个月前,我在手臂上纹了一个叉形炸弹,我跳过了空白,因为我觉得没有它们看起来更好.但令我沮丧的是,有时(并不总是)当我在shell中运行它时它不会启动一个fork炸弹,但它只是给出了一个语法错误.

bash: syntax error near unexpected token `{:'
Run Code Online (Sandbox Code Playgroud)

昨天它发生在我试图在朋友的Bash shell中运行它,然后我添加了空白,它突然工作,:(){ :|:& };:而不是:(){:|:&};:

空白是否重要; 我的胳膊上有语法错误吗?!

它似乎总是在zsh中工作,但在Bash中不起作用.

一个相关的问题没有解释关于空白的任何事情,这确实是我的问题; 为什么Bash需要的空白能够正确解析它?

Dmi*_*rov 267

在BASH中有一个用于分隔标记的字符列表.这些字符称为元字符,它们是|,&,;,(,),<,>,空间标签.另一方面,花括号({})只是构成单词的普通字符.

之前省略第二个空格},因为它&是一个元字符.因此,您的纹身应该至少有一个空格字符.

:(){ :|:&};:
Run Code Online (Sandbox Code Playgroud)

  • 简单的解决方案:将taoo的第一部分向左移动,并在两部分之间移植皮肤. (33认同)
  • 我喜欢这个词,"另一方面"......双关语意图?;):D(对不起,关于主题评论.) (23认同)
  • 但这对zsh来说有所不同吗?zsh以什么方式不同? (4认同)
  • 很好的解释,除了在这种情况下`{`和`}`是_shell关键字_。仅当由于周围的空间/元字符不足而无法识别它们时,它们才会被视为它们所包含的单词的字面部分。(然后是大括号扩展,发生在不同的上下文中。) (2认同)
  • @DmitriChubarov在命令名称中可以使用大括号(包括函数:{{foo}(){echo hello;}`。“ Name”,由bash`定义为“仅由字母数字和下划线组成的单词,并以开头带有字母字符或下划线的字符”,仅适用于变量名。 (2认同)

SzG*_*SzG 80

只是纹身一个

#!/bin/zsh
Run Code Online (Sandbox Code Playgroud)

在它上面的shebang,你会没事的.

  • 如果我们挑剔,那么shebang将无法工作,因为shell,希望是zsh,处于交互模式,正如提示所证明的那样...... (6认同)

Pet*_*ake 50

大括号更像是奇数关键字而不是特殊符号,并且需要空格.例如,这与括号不同.相比:

(ls)
Run Code Online (Sandbox Code Playgroud)

哪个有效,并且:

{ls}
Run Code Online (Sandbox Code Playgroud)

它查找命名的命令{ls}.要工作,必须是:

{ ls; }
Run Code Online (Sandbox Code Playgroud)

分号将关闭括号停止作为参数ls.

您所要做的就是告诉别人您正在使用具有相当窄的空格字符的比例字体.

  • @spydon或者你告诉他们你故意遗漏这个空间,以便人们从你的纹身中复制命令不会意外地运行它并使他们的机器崩溃;) (19认同)
  • @Alfe我在纹身之前尝试过它,但我在zsh中试过它,我认为它和bash一样解析.愚蠢的我,但我会告诉别人这是zsh.:) (14认同)
  • @DmitriChubarov - 这是一个非常偷偷摸摸的伎俩,使用完全不同的括号意义.它扩展了以逗号分隔的值列表,在本例中只是`ls`. (12认同)
  • 但是......男孩......你将在余生中获得纹身!你有史以来一直把自己标记为书呆子!然后_then_你甚至无法在缝合之前把它弄好吗?除了我的猜测之外,这是两个步骤;-)没有冒犯,朋友,我只是想知道. (7认同)
  • 嘿,如果它在zsh中有效,为什么不在它上方(或之前)添加#!/ bin/zsh?无论如何,首先指定shell是一个好习惯. (4认同)

Jer*_*fin 41

虽然在纹身字体中不容易看到,但是在支架和冒号之间实际上有一个字节顺序标记(BOM)(当你得到你没注意到它的纹身时,你可能已经充分陶醉了,但它确实存在) .这留下了三个明显的可能性

  1. 转录代码时,您无法输入BOM.结果是GIGO的明显应用.shell根本无法识别失败的转录中不存在的BOM.
  2. 你的外壳太旧了.它无法识别Unicode字符,因此BOM(以及可能是所有其他Unicode字符)被完全忽略,即使文件开头的任何地方的BOM都应被视为零宽度,不间断的空间.
  3. 你的shell太新了.不推荐使用BOM作为ZWNBS,并且作者已经实现了Unicode的未来版本,其中不再允许使用此用法.


dev*_*ull 40

然后我添加了空白,它突然起作用了......

这是因为shell解析的方式.在函数定义开始之后,即在之后需要一个空格{.

foo() { echo hey& }
foo() { echo hey&}
foo(){ echo hey&}
Run Code Online (Sandbox Code Playgroud)

是有效的.另一方面,

foo() {echo hey&}
Run Code Online (Sandbox Code Playgroud)

不是.


你真的需要像这样的纹身:

在此输入图像描述


来源:

  /* We ignore an open brace surrounded by whitespace, and also
     an open brace followed immediately by a close brace preceded
     by whitespace.  */
Run Code Online (Sandbox Code Playgroud)

{导致空格{echo被解释为单个标记之后省略空格.


一种等效的形式

:(){ :|:& };:
Run Code Online (Sandbox Code Playgroud)

将会

:(){
:|:& };:
Run Code Online (Sandbox Code Playgroud)

请注意,{备用版本之后没有空格,但换行符会导致shell识别{为令牌.