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

bash: syntax error near unexpected token `{:'

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

空格重要吗?我在手臂上纹了语法错误吗?!

它似乎总是在zsh中工作,但在Bash中不工作。

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


当前回答

在BASH中有一个分隔令牌的字符列表。这些字符被称为元字符,它们是|,&,;,(,),<,>,空格和制表符。另一方面,大括号({和})只是组成单词的普通字符。

省略}前面的第二个空格就可以了,因为&是元字符。因此,你的纹身至少应该有一个空格字符。

:(){ :|:&};:

其他回答

虽然在纹身字体中不容易看到,但在大括号和冒号之间实际上有一个字节顺序标记(BOM)(你可能在纹身时已经足够陶醉了,没有注意到它,但它确实存在)。这留下了三种明显的可能性:

You've failed to type in the BOM when you transcribed the code. The result is an obvious application of GIGO. The shell simply doesn't recognize a BOM that isn't present in your failed transcription. Your shell is too old. It doesn't recognize Unicode characters, so the BOM (and probably all other Unicode characters) is being ignored completely, even though a BOM anywhere but the beginning of a file is supposed to be treated as a zero-width, non-breaking space. Your shell is too new. Use of a BOM as a ZWNBS is deprecated, and the authors have implemented a future version of Unicode in which this usage is no longer allowed.

在BASH中有一个分隔令牌的字符列表。这些字符被称为元字符,它们是|,&,;,(,),<,>,空格和制表符。另一方面,大括号({和})只是组成单词的普通字符。

省略}前面的第二个空格就可以了,因为&是元字符。因此,你的纹身至少应该有一个空格字符。

:(){ :|:&};:

然后我加了空格,它突然起作用了…

这是因为壳层的解析方式。您需要在函数定义开始后,即在{。

foo() { echo hey& }
foo() { echo hey&}
foo(){ echo hey&}

是有效的。另一方面,

foo() {echo hey&}

不是。


你需要一个这样的纹身:


来源:

  /* We ignore an open brace surrounded by whitespace, and also
     an open brace followed immediately by a close brace preceded
     by whitespace.  */

省略{后面的空格会导致{回显被解释为单个标记。


等价形式的

:(){ :|:& };:

:(){
:|:& };:

注意,在替代版本中,{后面没有空格,但是换行符会使shell将{识别为标记。

大括号更像是奇怪的关键字,而不是特殊的符号,并且确实需要空格。例如,这与括号不同。比较:

(ls)

这是可行的,并且:

{ls}

查找名为{ls}的命令。为了工作,它必须:

{ ls; }

分号阻止将右大括号作为ls的参数。

你所要做的就是告诉人们你使用的是比例字体和一个相当窄的空格字符。

只要纹身

#!/bin/zsh

把它放在上面,你就没事了。