[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Is bash dying or dead (was Re: 4.1 is "$((( ))) an 'official operato

From: Linda Walsh
Subject: Re: Is bash dying or dead (was Re: 4.1 is "$((( ))) an 'official operator, if $(( )) isn't?
Date: Wed, 10 Aug 2011 17:44:39 -0700
User-agent: Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US; rv: Gecko/20100228 Thunderbird/ Mnenhy/

Eric Blake wrote:
On 08/10/2011 03:59 PM, Linda Walsh wrote:

Is this a fluke, due to the above changes NOT being 4.1? Or is this
construction going to break in 4.2:

'$((( )))'

According to POSIX, this construction should be parsed as an arithmetic substitution $(()) where the expression is (expr),
I was going by this note by chet:
 No.  The code is in there for a reason.  It's part of the fix for
 interpretation 217 (http://austingroupbugs.net/view.php?id=217).


Maybe I misunderstood the Posix verbage (not a far stretch), but it said:

0000217: The "single subshell" rule for $(( is not sufficient
Description     In the description of command substitution the standard says:

    If the command substitution consists of a single subshell, such as:

    $( (command) )

    a conforming application shall separate the "$(" and '(' into two
    tokens (that is, separate them with white space). This is required
    to avoid any ambiguities with arithmetic expansion.

In a discussion on the mailing list in December 2009, Philip Guenther
demonstrated that there are ambiguous cases other than the "single
subshell" case. He gave the example:

    cat=1; EOH=3; echo $(( cat <<EOH
    + ( (
    ) && ( cat <<EOH
    ) ) + 1 +

Current shell implementations treat this as an arithmetic expansion.

Thus the requirement on applications quoted above should be extended
to cover all ambiguous cases, not just the "single subshell" case.

The same requirement should also apply to nested subshells, so that
shells which implement the "(( arithmetic expression ))" extension
can apply the same disambiguation rules consistently to $((...)) and
        It sounded to me like $(( )) would be translated into "$( (xxxx) )",
turning off arithmetic expansion.  Did I read that incorrectly?

If not, then wouldn't
$((( ))) be turned into $( (( )) ), meaning the arith returns a status,
and not the calculation.  (I've tested this, and this is the case.

 if at all possible;
but if not possible, then it may also be parsed as a command substitution $() around either a double-subshell (()) or a shell extension of an arithmetic evaluation.

And since POSIX correctly states that this is implementation-specific, and involves shell heuristics, you are best off adding spaces to make it explicit which form you intended.

I wanted to evaluate something and assign result to a var.

gives me 'a=0', but

Not portable - lack of spacing means you fall foul of the ambiguity traps.
        Where would I add spacing?   Adding spacing after $( and before )
causes wrong eval.

a=$( ((-48-16+2**6)) )
will give 'a=<nothing>' -- understandable since the arith expression
merely sets status, it doesn't yield up it's value.

Not portable.
        I'm NOT concerned with portability to other shells!

A requirement of my programs is that they be run by bash -- I use so many bash extensions that rewriting to some 50% subset would put me off shell for another 10 years.

 While bash happened to use (( as an arith expression,
other shells may treat it as a double-subshell, and try to execute the

a=$(( (-48-16+2**6)))
        You mean like this
Ishtar:law> a=$( ((-48-16+2**6)))
Ishtar:law> echo $a
(no output)
Your suggestion doesn't work -- and THAT is my point.

There is little in the way of a workaround.

if you intended to assign a to the arithmetic expansion of the expression (-48-16+2**6); however, you are _still_ falling foul of using a bash extension (not all shells understand ** in arithmetic expansions),
        Whatever,  2*32....that wasn't the point.

If I use:
((a=-48-16+2**6)) ; throws an error. if -e is on, script exits

Bash extension. But the exit status of (()) makes sense as being non-zero for a result of 0, since the intended use of (()) is in control loops where the loop counter reaching 0 should abort the loop.
        And in a loop it is TESTED... while ((xxxx)), if ((xxxx), etc.
In those cases it WON't abort a script (usually)...it returns the result to the
conditional which does the 'right thing'.   It's when it is used as a simple
calculation and NOT as a value for a conditional that NOW causes the problem -- it
didn't used to.

  And once
the exit status makes sense, then the interaction with 'set -e' makes sense. Rather, you should realize that 'set -e', when rigidly defined, causes what seem to be very unintuitive results, and that NO AMOUNT OF COMPLAINING will ever make it more intuitive, so you are better off learning how to properly script without using 'set -e' as a crutch.
        This didn't used to be true -- so don't claim that it IS 'true', as it's
a arbitrary decision that may be true at some point in time, and false at other times. I.e. it isn't inherently true -- only because of the 'new' convention -- the old truth was that it didn't abort. and that truth has alot more history behind it.

Since 'let' functions the same as the above, then

'let' is a bash extension, not portable to POSIX.
Again, posix=don't care, let it function that way under the --posix switch.
(I didn't know let was a bash extension...)

Seems like POSIX has made bash as useful (or less so in some ways) as
borne shell.

Not true. POSIX has made bash more useful by making the portable constructs well-defined whether you are running on bash or any other portable shell, while still leaving bash room to provide extensions like (()) and let.
That's only if you use other shells -- if a pre-req of your product is running on bash, then it's a 'deficit'. Not alot of people DON't have access to bash.

It seems like POSIX is trying to kill off the usefulness of Bash -- and
that Bash is becoming 'sh+', rather than 'Bash'.

Not true.  Join the Austin Group,
        Oh, I'm sure they'd love me...

< and you will see that the goal of
POSIX is to standardize existing practice into something that can be commonly implemented by multiple people and safely relied on by multiple existing scripts, rather than worrying about implementation-specific extensions all over the place. If you can code to a common subset, your program becomes much more useful in practice.
I agree, but you can't program to the standard MS-API, and expect it to run on unix with any great easy (successes of wine aside). If you want portability -- then put the posix stuff in --posix, that is what it is FOR! But by making bash into posix compat, you lose advantages in bash.

POSIX is braindead.

I'm sorry you think so, but ranting on this list won't change POSIX.
I dunno if it was entirely a 'rant', I didn't just go off on posix. I gave what I felt were valid reasons why it was a problem. Ranting is just going on, and
not really justifying your position.

you don't like what POSIX is doing, then join the Austin Group (membership is free of charge) and submit your suggestions for improvements.
        You, Chet and the Austin group _may_ rue the day when you said this.  

Bash shouldn't follow posix unless in --posix mode, as posix mode is
worthless to program in -- as evidenced by the fact that you can no
longer do any calculation safely with let or (()),

'let' and (()) are not specified by POSIX, so you can't portably use them in --posix mode in the first place. --posix is VERY useful; it is what allows you to write scripts that work in bash, dash, ksh, zsh, and several other shells, without having to rewrite them every time you copy the script to a new machine.
        Then why enforce posix semantics on them?   If they are not of posix, 
not let them operate in 'useful mode'

 without fear that
your script will randomly die (oh just don't use command-exit-error
checking...) and you can no longer call functions safely.

'set -e' and function calls are one of the _fundamental_ non-intuitive designs of the historical shell. They were designed independently, and do not interact well.
I've always had them act predictably -- I found them invaluable in development as they'd stop where an error occurred and require me to fix. Not stopping/ignoring it, it goes on to future dependent steps that get very confused and can do 'bad thinks if previous steps didn't work.

  But given the latest POSIX wording, you can at
least apply consistent rules and rationally explain each behavior that you are seeing, and why what appears unintuitive actually complied with the standard; and you _can't_ change that non-intuitiveness without breaking existing scripts that have come to rely on the quirks as currently codified by POSIX.. The problem was that even in POSIX 2008, the POSIX wording had holes, it is not until the TC1 wording that the wording was tightened enough to actually be implementable by bash in a manner that matched ksh.
        Where there ya go.   That's the problem I _used_ to use ksh when it 
came out but when base came along, it was SO much better. ksh should be enhanced to match bash. The problem with software in general is poeple aiming for the lowest
common denominator

Bash is becoming very unstable -- programs that work in 3.1 won't
necessarily work in 3.2, those in 3.2 aren't compat with 4.0, 4.0 is
different than 4.1, and now 4.2 is different than 4.1.

That's because older bash has had bugs where it doesn't comply with POSIX, and those bugs have been fixed, but sometimes the fixes have consequences on the bash extensions. But if you use the POSIX subset, rather than the bash extensions, you should notice that newer bash is better, not worse, than older bash when it comes to running portable scripts.
        EXACTLY -- if people want posix strictures, they should use it.

How can people write stable scripts in an enironment of constant change?

By sticking to the common denominator that is known to work.
In other words, by ignoring everything that is 'bash', and sticking with --posix, in which case bash is worth less than nothing, as it takes up more memory and resources than posix compat shells like ash and ksh. The whole point of bash was to have MORE than posix.

Please people, am I being 'over-reactive'? Or are these valid

At least in my view, you are coming across as over-reactive and ranting, even if that was not your intent.
I can easily believe you feel that, that's why I asked -- I wonder too -- it seems like such an important issue, but so many don't seem to care, and it drives me crazy
(but then the world is like that in just about every field)

So I don't discount what you say, but I don't think you are seeing my point in bash being many 'ease of use/easy of programming' extensions on top of the POSIX base. It is for those things that have made bash the # linux shell. If it becomes another ksh, then
what's the point?

peace and more sadness than 'ranting'...

reply via email to

[Prev in Thread] Current Thread [Next in Thread]