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), 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.
so:
a=$(((-48-16+2**6)))
gives me 'a=0', but
Not portable - lack of spacing means you fall foul of the ambiguity traps.
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. While bash happened to use (( as an arith expression,
other shells may treat it as a double-subshell, and try to execute the
command that results from expanding the glob -48-16+2**6 as a file name.
How do I assign something to a?
Use:
a=$(( (-48-16+2**6)))
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), so you may still end up executing a command substitution
over a double-subshell unless you rewrite your arithmetic expression to
comply with POSIX (but POSIX doesn't have any way to do exponentiation).
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 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.
Since 'let' functions the same as the above, then
'let' is a bash extension, not portable to POSIX.
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.
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, 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.
POSIX is braindead.
I'm sorry you think so, but ranting on this list won't change POSIX. If
you don't like what POSIX is doing, then join the Austin Group
(membership is free of charge) and submit your suggestions for improvements.
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.
> 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. 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.
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.
How can people write stable scripts in an enironment of constant change?
By sticking to the common denominator that is known to work.
Please people, am I being 'over-reactive'? Or are these valid
concerns?
At least in my view, you are coming across as over-reactive and ranting,
even if that was not your intent.
--
Eric Blake ebl...@redhat.com +1-801-349-2682
Libvirt virtualization library http://libvirt.org