Why is whitespace sometimes needed around metacharacters?
几个月前,我在手臂上纹了一个叉形炸弹,我跳过了空白,因为没有它们我觉得它看起来更好。但令我沮丧的是,有时(不总是)当我在一个外壳里运行它时,它不会启动一个分叉炸弹,但它只是给出了一个语法错误。
1
| bash: syntax error near unexpected token `{:' |
昨天,我试着在朋友的弹壳里运行它,然后加上空白,它突然工作了,用:(){ :|:& };:代替:(){:|:&};:。
空白有关系吗?我手臂上纹了语法错误吗?!
它似乎总是在zsh中工作,但在bash中不工作。
一个相关的问题不能解释关于空白的任何东西,这确实是我的问题;为什么bash需要空白来正确地解析它?
- 我在这里贴了同样的问题(不包括纹身部分)。
- 此外,冒号(:)不能用作函数名(请参见:pubs.opengroup.org/onlinepubs/9699919799/utilities/…)…freebsd's/bin/sh甚至在这方面给出了一个错误…
- @地毯烟鬼:我不知道这有什么关系。这个问题是关于bash的。
在bash中有一个分隔令牌的字符列表。这些字符称为元字符,分别是|、&、;、(、)、<、>、空格和制表符。另一方面,大括号({和}只是组成单词的普通字符。
在}之前省略第二个空格就行了,因为&是一个元字符。因此,您的纹身应该至少有一个空格字符。
- 简单的解决方法:将桃子的第一部分向左移动,在两部分之间移植皮肤。
- 我喜欢这个词,on the other hand……双关语?;):d(抱歉,对于主题外的评论。)
- 但是这对zsh来说是不同的?zsh有什么不同?
- 很好的解释,除了{和}在本文中是shell关键字。只有当它们没有被识别出来时(由于缺少周围的空格/元字符),它们才会被视为它们成为单词的一部分。(然后是大括号扩展,它发生在不同的上下文中。)
- @mklement0谢谢,good point,{和}是单字符关键字。由于名称中不允许使用大括号,因此将它们与其他字符组合以形成较长的单词几乎没有用处。但是您需要用一个分隔符来分隔它们。
- @命令名中允许使用dmitricubarov大括号(包括函数:{foo} () { echo hello; })。名称",如bash中定义为"仅由字母数字字符和下划线组成,以字母字符或下划线开头的单词",仅适用于变量名。
只是纹身
她在上面,你会没事的。
- 如果我们挑剔的话,shebang根本不起作用,因为shell,希望zsh,处于交互模式,这一点可以通过提示来证明…
- 那就在它前面运行命令zsh!
大括号比特殊符号更像奇数关键字,并且确实需要空格。例如,这与括号不同。比较:
哪些有效,以及:
它查找名为{ls}的命令。要工作,必须:
分号停止将右大括号作为ls的参数。
你所要做的就是告诉人们你使用的是一种比例字体,它有一个相当窄的空格字符。
- 但是,{ls,}起作用;—)
- @不,这不是复合语句。
- @德米特里库巴罗夫-这是一个非常狡猾的伎俩,使用了完全不同的含义的牙套。它扩展了逗号分隔的值列表,在本例中,它只是ls。
- 我只是在装傻。别把我最后的评论看得太认真;-)
- 但是……孩子……你的余生都要纹身了!你一直把自己当成书呆子!然后你连缝针前都没法把它缝好?我想,这比成为书呆子要多出两步;-)不冒犯,伙计,我只是想知道。
- @alfe我在纹身之前试过,但是我在zsh中试过,我认为它和bash有相同的解析。我太傻了,但我会告诉别人这是zsh。:)
- @Spydon或者你告诉他们你故意遗漏了空间,这样人们从你的纹身上复制命令时就不会意外地运行它并撞坏他们的机器;)
- @他在澳大利亚:现实是颠倒的;-)但是,更严重的是,原始的可以在""之前用逗号固定,而不是在""之后需要一个空格吗?也许纹身师能把它插进去?(或者您的逗号示例只适用于ls吗?)
- 不,因为前面的部分,而且不管块中是否有逗号,这个左大括号都被解释为一个函数块打开器。
- 嘿,如果它在zsh中有效,为什么不加上!/箱子/zsh就在上面(或前面)?无论如何,最好先指定外壳。
虽然在塔图字体中不容易看到,但括号和冒号之间实际上有一个字节顺序标记(bom)(当你得到塔图时,你可能已经喝得醉透了,但你没有注意到它,但它确实存在)。这留下了三个明显的可能性:
当您转录代码时,您未能输入BOM。结果表明,该方法具有很好的应用前景。shell根本不识别在失败的转录中不存在的bom。
你的壳太旧了。它不识别unicode字符,所以bom(以及可能所有其他unicode字符)被完全忽略,即使bom在除文件开头之外的任何位置都被视为零宽度、不间断的空格。
你的外壳太新了。不赞成将BOM用作zwnbs,作者已经实现了以后的Unicode版本,在该版本中不再允许使用这种用法。
and then I added the whitespace and it suddenly worked ...
这是因为shell是如何解析的。在函数定义开始后,即在{之后,需要一个空格。
1 2 3
| foo() { echo hey& }
foo() { echo hey&}
foo(){ echo hey&} |
是有效的。另一方面,
不是。
你实际上需要这样的塔图:
来源:
1 2 3
| /* We ignore an open brace surrounded by whitespace, and also
an open brace followed immediately by a close brace preceded
by whitespace. */ |
在{后面省略一个空格会导致{echo被解释为单个令牌。
等价形式
将是
注意,在备用版本中,{之后没有空格,但是换行符会导致shell将{识别为令牌。