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

Reply via email to