几个月前,我在手臂上纹了一个 fork bomb,我跳过了空格,因为我觉得没有它们看起来更好看。但令我沮丧的是,有时(并非总是)当我在 shell 中运行它时,它不会启动 fork 炸弹,而只会给出语法错误。
bash: syntax error near unexpected token `{:'
昨天,当我尝试在朋友的 Bash shell 中运行它时发生这种情况,然后我添加了空格,它突然起作用了,:(){ :|:& };:
而不是 :(){:|:&};:
空格是否重要?我在手臂上纹了语法错误吗?!
它似乎总是在 zsh 中工作,但在 Bash 中却不行。
A related question 没有解释任何关于空格的内容,这确实是我的问题; 为什么 Bash 需要空格才能正确解析它?
BASH 中有一个分隔标记的字符列表。这些字符称为元字符,它们是 |
、&
、;
、(
、)
、<
、>
、空格 和 标签。另一方面,花括号({
和 }
)只是组成单词的普通字符。
省略 }
之前的第二个空格也可以,因为 &
是一个元字符。因此,你的纹身应该至少有一个空格字符。
:(){ :|:&};:
只纹一个
#!/bin/zsh
shebang 在它上面,你会没事的。
大括号更像是奇怪的关键字而不是特殊符号,并且确实需要空格。例如,这与括号不同。相比:
(ls)
哪个有效,并且:
{ls}
它查找名为 {ls}
的命令。要工作,它必须是:
{ ls; }
分号停止将右大括号作为 ls
的参数。
您所要做的就是告诉人们您正在使用具有相当窄空格字符的比例字体。
ls
。
虽然在纹身字体中不容易看到,但实际上在大括号和冒号之间有一个字节顺序标记(BOM)(当你得到纹身时你可能已经陶醉了,以至于你没有注意到它,但它确实存在) .这留下了三个明显的可能性:
您在转录代码时未能输入 BOM。结果是GIGO的明显应用。 Shell 根本无法识别失败的转录中不存在的 BOM。你的外壳太旧了。它不识别 Unicode 字符,因此 BOM(可能还有所有其他 Unicode 字符)被完全忽略,即使除了文件开头以外的任何地方的 BOM 都应该被视为零宽度、不间断的空间.你的外壳太新了。不推荐使用 BOM 作为 ZWNBS,作者已经实现了 Unicode 的未来版本,其中不再允许这种用法。
然后我添加了空格,它突然起作用了......
这是因为 shell 的解析方式。在函数定义开始后,即{
之后,您需要一个空格。
foo() { echo hey& }
foo() { echo hey&}
foo(){ echo hey&}
是有效的。另一方面,
foo() {echo hey&}
不是。
你实际上需要这样的纹身:
https://i.stack.imgur.com/w2Dmj.png
从 source:
/* We ignore an open brace surrounded by whitespace, and also
an open brace followed immediately by a close brace preceded
by whitespace. */
在 {
之后省略一个空格会导致 {echo
被解释为单个标记。
的等价形式
:(){ :|:& };:
将会
:(){
:|:& };:
请注意,备用版本中 {
之后没有空格,但换行符会导致 shell 将 {
识别为标记。
{echo
的命令?
不定期副业成功案例分享
on the other hand
...双关语? ;) :D (对不起,偏离主题的评论。){
和}
在这种情况下是 shell 关键字。只有当它们没有被这样识别时——由于缺少周围的空格/元字符——它们才会被视为它们成为的单词的字面部分。 (然后是大括号扩展,它发生在不同的上下文中。){foo} () { echo hello; }
。“名称”,在bash
中定义为“仅由字母数字字符和下划线组成并以字母字符或下划线开头的单词”,仅适用于变量名。