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

本文翻译自:Why is whitespace sometimes needed around metacharacters?

A few months ago I tattooed a fork bomb on my arm, and I skipped the whitespaces, because I think it looks nicer without them. 几个月前,我在手臂上纹了一个叉形炸弹 ,我跳过了空白,因为我觉得没有它们看起来更好。 But to my dismay, sometimes (not always) when I run it in a shell it doesn't start a fork bomb, but it just gives a syntax error. 但令我沮丧的是, 有时 (并不总是)当我在shell中运行它时它不会启动一个fork炸弹,但它只是给出了一个语法错误。

bash: syntax error near unexpected token `{:'

Yesterday it happened when I tried to run it in a friend's Bash shell, and then I added the whitespace and it suddenly worked, :(){ :|:& };: instead of :(){:|:&};: 昨天它发生在我试图在朋友的Bash shell中运行它,然后我添加了空格,它突然起作用, :(){ :|:& };:而不是:(){:|:&};:

Does the whitespace matter; 空白是否重要; have I tattooed a syntax error on my arm?! 我的胳膊上有语法错误吗?!

It seems to always work in zsh , but not in Bash. 它似乎总是在zsh中工作,但在Bash中不起作用。

A related question does not explain anything about the whitespaces, which really is my question; 一个相关的问题没有解释关于空白的任何事情,这确实是我的问题; Why is the whitespace needed for Bash to be able to parse it correctly? 为什么Bash需要的空白能够正确解析它?


#1楼

参考:https://stackoom.com/question/1QtdM/为什么元字符周围有时需要空格


#2楼

Braces are more like odd keywords than special symbols, and do need spaces. 大括号更像是奇数关键字而不是特殊符号,并且需要空格。 This is different to parentheses, for example. 例如,这与括号不同。 Compare: 相比:

(ls)

which works, and: 哪个有效,并且:

{ls}

which looks for a command named {ls} . 它查找名为{ls}的命令。 To work, it has to be: 要工作,必须是:

{ ls; }

The semicolon stops the closing brace being taken as a parameter to ls . 分号将关闭括号停止作为ls的参数。

All you have to do is tell people that you are using a proportional-font with a rather narrow space character. 您所要做的就是告诉别人您正在使用具有相当窄的空格字符的比例字体。


#3楼

and then I added the whitespace and it suddenly worked ... 然后我添加了空白,它突然起作用了......

It's because of how the shell parses. 这是因为shell解析的方式。 You need a space after the function definition begins, ie after the { . 在函数定义开始之后,即在{之后,您需要一个空格。

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

are valid. 是有效的。 On the other hand, 另一方面,

foo() {echo hey&}

isn't. 不是。


You actually need a tatoo like this: 你真的需要像这样的纹身:

在此输入图像描述


From the source : 来源

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

Omitting a space after the { causes the {echo to be interpreted as a single token. {导致{echo被解释为单个标记之后{省略空格。


An equivalent form of 一种等效的形式

:(){ :|:& };:

would be 将会

:(){
:|:& };:

Note that there is no space after { in the alternate version, but a line-break causes the shell to recognize { as a token. 请注意, {在备用版本之后没有空格,但换行符会导致shell识别{作为标记。


#4楼

There is a list of characters that separate tokens in BASH. 在BASH中有一个用于分隔标记的字符列表。 These characters are called metacharacters and they are | 这些字符称为元字符 ,它们是| , & , ; & ; , ( , ) , < , > , space and tab . ()<>空格制表符 On the other hand, curly braces ( { and } ) are just ordinary characters that make up words. 另一方面,花括号( {} )只是构成单词的普通字符。

Omitting the second space before } will do, since & is a metacharacter. }之前省略第二个空格将会这样做,因为&是一个元字符。 Therefore, your tattoo should have at least one space character. 因此,您的纹身应该至少有一个空格字符。

:(){ :|:&};:

#5楼

Although not easily visible in the tatoo font, there's actually a Byte-Order Mark (BOM) between the brace and the colon (you may have been sufficiently intoxicated when you got the tatoo that you didn't notice it, but it's really there). 虽然在纹身字体中不容易看到,但是在支架和冒号之间实际上有一个字节顺序标记(BOM)(当你得到你没注意到它的纹身时,你可能已经充分陶醉了,但它确实存在) 。 This leaves three obvious possibilities: 这留下了三个明显的可能性

  1. You've failed to type in the BOM when you transcribed the code. 转录代码时,您无法输入BOM。 The result is an obvious application of GIGO. 结果是GIGO的明显应用。 The shell simply doesn't recognize a BOM that isn't present in your failed transcription. shell根本无法识别失败的转录中不存在的BOM。
  2. 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. 它无法识别Unicode字符,因此BOM(以及可能是所有其他Unicode字符)被完全忽略,即使文件开头的任何地方的BOM都应被视为零宽度,不间断的空间。
  3. Your shell is too new. 你的shell太新了。 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. 不推荐使用BOM作为ZWNBS,并且作者已经实现了Unicode的未来版本,其中不再允许使用此用法。

#6楼

Just tattoo a 只是纹身一个

#!/bin/zsh

shebang above it and you'll be fine. 在它上面的shebang,你会没事的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值