Is the following snippet valid Bourne shell code?

110 views Asked by At

The following snippet triggers a syntax error when interpreted by bash 4.3.39(1) but not by zsh 5.0.5.

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

Have I just found a bug in bash parser?

2

There are 2 answers

2
chepner On BEST ANSWER

It's not a bug; from the man page:

The following redirection operators may precede or appear anywhere within a simple command or may follow a command.

So

>/dev/null echo foo
echo >/dev/null foo
echo foo >/dev/null

are all legal and equivalent, but the redirection must follow the compound command {...}.

Because { has no real special meaning to bash (alias {=foo makes { and alias for foo), the line 1>&2 { is parsed as a simple command, with the assumption that the lookup for { will succeed when eprintf is eventually called. As a result, the first } closes the compound statement serving as the body of the function, and the second one is unmatched and triggers the syntax error.

I couldn't say without further research why bash and zsh differ here, only that it is documented behavior for bash.

4
Vincent De Baere On

According to the Single Unix Specification, Shell and Utilities Volume, the function definition command syntax is:

fname() compound-command[io-redirect ...]

In your case that would give:

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

The function definition command syntax only allows for one compound command, moreover, compound commands ( { ... } ) do not have any io redirection mentioned in the syntax, functions do.

So according to my reading of the standard, this really doesn't look much like a bug.