On Mon, Aug 31, 2026 at 08:16:12AM +0700, Robert Elz wrote:
> From: Martin D Kealey <[email protected]>
> Message-ID:
> <CAN_U6MUio0N-Xkb5TMgwTHJX+=FvP9Oe3m_jNcB=u=js-v2...@mail.gmail.com>
>
> In places like after "if" "then" "else" "do" "{" "(" "|" "&&" "||" ...
> commands are required.
>
> | but not after ?{? or ?(? or ?|??
>
> Those are a reserved work, and operators - they all require a command
> to follow.
>
> | POSIX is, erm… idiosyncratic, but why enforce such limitations when not
> | doing so would simplify the grammar? What have I missed?)
>
> The grammar in this regard is quite simple, it turns out that empty commands
> are easy to permit in a recursive-descent parser (just look at what is
> coming next before deciding what to do) but tricker in simple grammar
> bases parsers (without creating conflicts). It is also mostly consistent
> (but the original was recursive descent, and with those, lots of weirdness
> is easily possible.)
>
> kre
>
> ps: The NetBSD shell doesn't enforce the "no empty statements" in exactly
> one place, we allow:
> empty() { }
Nice.
> [In bash, one can use just '!' as the command:
> empty() { !; }
> anywhere a command is required, but that is, like our '{ }', non-standard.
$ empty
bash: !: event not found
A space is needed between the '!' and the ';':
$ empty() { ! ; }
When using 'set -e', prevent exits with:
$ empty() { ! ! ; }
Things are a bit weird around !
$ ! ## $? = 1
$ ! ! ## $? = 0
$ ! ; ## $? = 1
$ ( set -e; ! ; echo foo ) ## foo (expected no output)
Which looks like a minor issue.
> It probably isn't documented though, I didn't check, so don't assume it
> won't get fixed sometime.]
>From the bash manual:
The format for a pipeline is:
[time [-p]] [ ! ] command1 [ [|⎪|&] command2 ... ]
Assuming command1 can not be empty (which is not explicitly documented).
In the bash-implementation a pipeline is more like:
[time [-p]] [ ! ] [ command1 [ [|⎪|&] command2 ... ] ]
As also valid are:
$ time
$ time !
> Not enforcing the rule in other places doesn't really give anyone any
> benefits.
Being able to leave out the last ';' in { ... } would be really nice.
Saves typing (especially interactively) and would allow 'empty() { }' too.
It is also backwards compatible, scripts would already have been broken.
--
Regards, Mike Jonkmans