bash 为什么有时在元字符周围需要空格?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/21186724/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Why is whitespace sometimes needed around metacharacters?
提问by spydon
A few months ago I tattooed a fork bombon 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 Bashshell, and then I added the whitespace and it suddenly worked, :(){ :|:& };:
instead of :(){:|:&};:
昨天当我试图在朋友的Bashshell 中运行它时发生了它,然后我添加了空格,它突然起作用了,:(){ :|:& };:
而不是:(){:|:&};:
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 questiondoes 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 需要空格才能正确解析它?
采纳答案by Dmitri Chubarov
There is a list of characters that separate tokens in BASH. These characters are called metacharactersand they are |
, &
, ;
, (
, )
, <
, >
, spaceand tab. On the other hand, curly braces ({
and }
) are just ordinary characters that make up words.
BASH 中有一个用于分隔令牌的字符列表。这些字符称为元字符,它们是|
, &
, ;
, (
, )
, <
, >
, space和tab。另一方面,花括号({
和}
)只是组成单词的普通字符。
Omitting the second space before }
will do, since &
is a metacharacter. Therefore, your tattoo should have at least one space character.
省略之前的第二个空格}
就可以了,因为它&
是一个元字符。因此,你的纹身应该至少有一个空格字符。
:(){ :|:&};:
回答by SzG
Just tattoo a
就纹个
#!/bin/zsh
shebang above it and you'll be fine.
shebang 在它上面,你会没事的。
回答by Peter Westlake
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}
. To work, it has to be:
它查找名为{ls}
. 要工作,它必须是:
{ 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.
您所要做的就是告诉人们您使用的是带有相当窄空格字符的比例字体。
回答by Jerry Coffin
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). This leaves three obvious possibilities:
虽然在纹身字体中不容易看到,但实际上在大括号和冒号之间有一个字节顺序标记(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.
- 您在转录代码时未能输入 BOM。结果是 GIGO 的明显应用。外壳根本无法识别失败的转录中不存在的 BOM。
- 你的壳太旧了。它不识别 Unicode 字符,因此 BOM(可能还有所有其他 Unicode 字符)被完全忽略,即使除了文件开头以外的任何地方的 BOM 都应该被视为零宽度、不间断的空间.
- 你的外壳太新了。不推荐使用 BOM 作为 ZWNBS,作者已经实现了 Unicode 的未来版本,其中不再允许这种用法。
回答by devnull
and then I added the whitespace and it suddenly worked ...
然后我添加了空格,它突然起作用了......
It's because of how the shell parses. You need a space after the function definition begins, i.e. after the {
.
这是因为shell如何解析。函数定义开始后需要一个空格,即{
.
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.
请注意,{
替代版本中的after 没有空格,但换行符会导致 shell 将其识别{
为标记。