提问人:spydon 提问时间:1/17/2014 最后编辑:codeforesterspydon 更新时间:8/1/2018 访问量:81064
为什么有时元字符周围需要空格?
Why is whitespace sometimes needed around metacharacters?
问:
几个月前,我在胳膊上纹了一个叉子炸弹,我跳过了空格,因为我认为没有它们看起来更好。但令我沮丧的是,有时(并非总是)当我在 shell 中运行它时,它不会启动分叉炸弹,但它只是给出语法错误。
bash: syntax error near unexpected token `{:'
昨天当我尝试在朋友的 Bash shell 中运行它时发生了这种情况,然后我添加了空格,它突然起作用了,而不是:(){ :|:& };:
:(){:|:&};:
空白重要吗?我的胳膊上有语法错误吗?!
它似乎总是在 zsh 中工作,但在 Bash 中不起作用。
一个相关的问题没有解释任何关于空格的事情,这确实是我的问题;为什么 Bash 需要空格才能正确解析它?
答:
大括号更像是奇数关键字,而不是特殊符号,并且确实需要空格。例如,这与括号不同。比较:
(ls)
有效,以及:
{ls}
它查找名为 的命令。要工作,它必须是:{ls}
{ ls; }
分号停止将右大括号作为 的参数。ls
你所要做的就是告诉人们你使用的是比例字体,具有相当窄的空格字符。
评论
ls
然后我添加了空格,它突然起作用了......
这是因为 shell 的解析方式。在函数定义开始之后,即在 .{
foo() { echo hey& }
foo() { echo hey&}
foo(){ echo hey&}
是有效的。另一方面
foo() {echo hey&}
不是。
你实际上需要一个这样的tatoo:
从源头:
/* 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
在 BASH 中有一个分隔标记的字符列表。这些字符称为元字符,它们是 、 、 、 、 、 和 制表符。另一方面,大括号 ( 和 ) 只是构成单词的普通字符。|
&
;
(
)
<
>
{
}
省略前面的第二个空格就可以了,因为是一个元字符。因此,你的纹身应该至少有一个空间字符。}
&
:(){ :|:&};:
评论
on the other hand
{
}
{foo} () { echo hello; }
bash
虽然在 tatoo 字体中不容易看到,但大括号和冒号之间实际上有一个字节顺序标记 (BOM)(当你拿到 tatoo 时,你可能已经陶醉了,以至于你没有注意到它,但它确实在那里)。这留下了三种明显的可能性:
- 您在转录代码时未能键入 BOM。其结果是GIGO的明显应用。shell 根本无法识别失败的听录中不存在的 BOM。
- 你的壳太旧了。它无法识别 Unicode 字符,因此 BOM(可能还有所有其他 Unicode 字符)被完全忽略,即使文件开头以外的任何位置的 BOM 都应该被视为零宽度、不间断的空格。
- 你的外壳太新了。不推荐将 BOM 用作 ZWNBS,作者已经实现了 Unicode 的未来版本,其中不再允许这种用法。
只需纹身
#!/bin/zsh
Shebang 在上面,你会没事的。
评论