Bash 以下代码段是否为有效的Bourne shell代码?

Bash 以下代码段是否为有效的Bourne shell代码?,bash,syntax-error,sh,Bash,Syntax Error,Sh,以下代码段在由bash4.3.39(1)而不是zsh5.0.5解释时触发语法错误 eprintf() { 1>&2 { printf "$@" printf '\n' } } 我刚刚在bash解析器中发现了一个bug吗?根据《单一Unix规范、Shell和实用程序》卷,函数定义命令语法为: fname() compound-command[io-redirect ...] 在您的情况下,这将给出: eprintf() { prin

以下代码段在由bash4.3.39(1)而不是zsh5.0.5解释时触发语法错误

eprintf()
{
    1>&2 {
        printf "$@"
        printf '\n'
    }
}

我刚刚在bash解析器中发现了一个bug吗?

根据《单一Unix规范、Shell和实用程序》卷,函数定义命令语法为:

fname() compound-command[io-redirect ...]
在您的情况下,这将给出:

eprintf() { printf "$@" ; printf '\n' } >&2
函数定义命令语法只允许一个复合命令,而且,复合命令(
{…}
)没有语法中提到的任何io重定向,函数有


因此,根据我对标准的理解,这看起来真的不太像一个bug。

它不是bug;从手册页:

以下重定向运算符可能位于前面或出现 简单命令内的任何位置,或者可以跟随命令

所以

都是合法且等效的,但重定向必须遵循复合命令
{…}

由于
{
bash
没有真正的特殊意义(
别名{=foo
使
{
foo的别名
),因此
1>&2{
行被解析为一个简单的命令,假设
{
将在最终调用
eprintf
时成功。因此,第一个
}
关闭作为函数体的复合语句,第二个语句不匹配并触发语法错误


如果没有进一步的研究,我无法解释为什么
bash
zsh
在这里有所不同,只是它是
bash

的记录行为。看起来bash将第一个右大括号解释为函数的结尾…看起来像一个bug。请报告它。出于兴趣,如果你移动重拨,这是否能像预期的那样工作在块之后执行什么操作?我在规范中找不到任何支持它的内容,但在进行此更改时,只会抱怨格式字符串中的变量。问题是函数内部复合语句的重定向,而不是函数体本身的重定向。没有任何东西阻止您放置一个复合语句语句。特别提到函数重定向是因为它是在调用函数时应用的,而不是在定义函数时应用的。(另外,因为函数定义在语法上与命令不同。)重定向可以应用于任何命令,无论是简单的还是复合的(包括
{…}
(…)
if
while
till
case
,等等。)@chepner我的回答是错误的,复合命令在这样一个复合命令结束时接受重定向(复合命令内的重定向会覆盖复合命令重定向)IMO在语法上不正确(在Burne shell中)在IO(复合)命令之前指定IO重定向:准备IO重定向是我认为的“BasHistic”,因此不一定是有效的Burne shell代码。然后,这又取决于到底是什么“Burne shell”。。嵌套复合命令也是如此。如果我正确阅读规范:无效。考虑到问题是这是否是
bash
解析器中的错误,我将标题视为输入错误。感谢您编写答案,bash团队提示我进入手册页,我是否找到了您引用的段落。至少可以说,这非常奇怪!L真的,Shellcheck抓住了这个错误!是的,你通常必须非常仔细地阅读这个人的页面,以找出其中的细微之处。我正在写一个关于为什么这是一个bug的答案,当我终于注意到简单和复合命令的用法上的差异时:
>/dev/null echo foo
echo >/dev/null foo
echo foo >/dev/null