本文翻譯自: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: 你真的需要像這樣的紋身:
/* 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: 這留下了三個明顯的可能性
- 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。
- 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都應被視爲零寬度,不間斷的空間。
- 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,你會沒事的。