From: John Kelly on
On Mon, 21 Jun 2010 14:06:00 -0400, Wayne <nospan(a)all.invalid> wrote:

>The shells of the 1970s and 1980s were brilliant, but not perfect and
>time marches on.

Perhaps, but I don't there's been anything good since about 1986 or so.
Or maybe I'm just getting old and grouchy. ;-)


--
Web mail, POP3, and SMTP
http://www.beewyz.com/freeaccounts.php

From: Janis Papanagnou on
On 21/06/10 20:06, Wayne wrote:
> On 6/21/2010 9:35 AM, Janis Papanagnou wrote:
>> On 20/06/10 18:22, Martin Vaeth wrote:
>>> John Kelly <jak(a)isp2dial.com> wrote:
>>>> <vaeth(a)mathematik.uni-wuerzburg.de> wrote:
>>>>
>>>>> case $1 in -*) false;; esac || echo "$start with -"
>>>>
>>>> I think that's harder to read.
>>>
>>> Maybe, but it is standard and fast.
>>> More important: You can use it like "test" in loops like
>>>
>>> while ! case $arg in -*) false;; esac
>>> do set_something_and_read_next_arg
>>> done
>>
>> A few notes...
>>
>> If, as your example seems to show, you intend to parse options you
>> should prefer using getopts, which is much clearer and more powerful
>>
>> while getopts ...
>> do ...
>> done
>>
>> Then, why did you use double negation, /false/ and /!/, which makes
>> your construct even less legible.
>
>
> The case construct returns 0 (true) if no cases match.

Good point. That's another reason to avoid that construct for the
given purpose, since specifying the case expression completely (to make
it better maintainable), including the "otherwise" branch, will bloat
the code further.

> So you
> need to return false for a match, and then negate the result to have
> true for a match and false for no match. I think the construct
>
> if case "$word" in (-*) true;; esac
>
> returns true (0) whether or not there is a match.
>
>> Another point is that the negation
>> operator /!/ isn't guaranteed to be supported in non-modern shells.
>
> You make a good point. The case statement and "!" negation are part of
> POSIX and thus are very portable across all modern and most historical
> shells.

Right. I thought /!/ was unsupported by SUS, but I was apparently
misremembering. Thanks.

This is especially interesting; I thought ksh88 was POSIX conformant,
but it did not support /!/. Had that been a later addition to POSIX?

> The "[[ ... ]]" syntax is very useful and supported by the most
> popular shells today, but it is not standardized. Solaris /bin/sh for
> example doesn't support "[[ ... ]]", but doesn't support "!" either.

Solaris is in some respect an own issue. But I am well aware that
both are constructs you still cannot rely on in practise.

>
>> And if you use a modern shell you can as well use the [[...]] test
>> construct which is a lot more legible that the more portable case.
>
> The shells of the 1970s and 1980s were brilliant, but not perfect and
> time marches on. Today it seems one must choose between historical
> compatibility and modern functionality and readability. I agree with
> Janis, using "[[ ... ]]" for pattern matching is better if you use a
> modern shell.
>
>> Though, in case of using case, you may want to use this syntax
>>
>> case $arg in (-*) false;; esac
>>
>> (mind the parenthesis) which is more robust in certain lexical shell
>> contexts.
>
> But not all historical shells support this. I don't think Solaris /bin/sh
> does.

Likely not all historical shells support this. I'm curious to know
the ones that do and those that don't support it.

Janis

>
>>
>> (There was another point I wanted to mention that I forgot... - anyway.)
>>
>> Janis
>

From: Sven Mascheck on
Wayne wrote:

IMHO, you're repeatedly mixing up POSIX and traditional portability.

> The case statement and "!" negation are part of POSIX and thus are
> very portable across all modern and most historical shells.

Your "thus" is misleading (concerning "historical shells").
POSIX is not really concerned about historical behaviour/shells but
about "existing practice". Concerning shell, POSIX mainly implements
the korn shell (and ksh implemented ! with ksh88e).
"Historical" means almost always the traditional Bourne shell.
! was not implemented, yet, then.


> The "[[ ... ]]" syntax is very useful and supported by the most
> popular shells today, but it is not standardized. Solaris /bin/sh for
> example doesn't support "[[ ... ]]", but doesn't support "!" either.

The standard is not relevant concerning the traditional Bourne shell.
I wonder if you're trying to suggest a relation here.


>> And if you use a modern shell you can as well use the [[...]] test
>> construct which is a lot more legible that the more portable case.

No, not all modern shells implement [[ ... ]], and POSIX doesn't
implement it. Using [[ ... ]] is a tradeoff.


>> case $arg in (-*) false;; esac
>
> But not all historical shells support this. I don't think Solaris /bin/sh
> does.

.... beacause the parenthesis form of command subtitution was not
implemented, yet. Thus, the above was just not needed, yet.
Strictly speaking, the opening paren should never have been necessary, because
it just compensates for a flaw in the parser of some modern shells [1].
All almquist shells in contrast work well without the opening paren.

[1] http://www.in-ulm.de/~mascheck/various/cmd-subst/
From: Geoff Clare on
Janis Papanagnou wrote:

> This is especially interesting; I thought ksh88 was POSIX conformant,
> but it did not support /!/. Had that been a later addition to POSIX?

The POSIX shell description was based on ksh88 but with some
modifications. Obviously the original ksh88 did not implement
those modifications, so it was not POSIX conformant. Systems that
use ksh88 as their POSIX shell had to modify it to be conformant.

Later versions of ksh88 added the "missing" POSIX features such
as ! and $((...)), but are still not conformant in some ways.
That's why /usr/xpg4/bin/sh and /bin/ksh are different binaries
in Solaris 10.

One difference that springs to mind is:

$ ksh -c 'echo $((010))'
10
$ sh -c 'echo $((010))'
8

--
Geoff Clare <netnews(a)gclare.org.uk>