[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: behavior of arithmetic evaluation operator inside extended test oper
Re: behavior of arithmetic evaluation operator inside extended test operator
Tue, 19 May 2020 23:04:34 +0530
Thanks Greg for the explanation. Yes your explanation aligns with my
My recommendation was to check if this behavior needs to be documented as a
side-note in this section of
explain that, any other primaries other than the ones mentioned above will
be evaluated as a literal string result. I also tried finding an
explanation in your wiki at
https://mywiki.wooledge.org/BashGuide/TestsAndConditionals, but there
wasn't an explicit point made.
On Tue, May 19, 2020 at 7:40 PM Greg Wooledge <address@hidden> wrote:
> On Tue, May 19, 2020 at 06:10:30PM +0530, Inian Vasanth wrote:
> > The behavior of arithmetic context operator $((..)) inside [[..]] is not
> > well defined.
> It's simply a substitution. The $(( )) is evaluated, and the result
> is placed into the [[ ]] command as a word.
> > The downside is the operator
> > without $ when used as ((..)) just behaves as double grouping,
> Correct, as you demonstrated below.
> > but $((..))
> > behaves as a valid arithmetic evaluation followed by non empty string
> > comparison `-n`
> Well, yes. What did you *expect*? What are you trying to do?
> > bash -cx '[[ (( 100 < 3 )) ]] && echo ok'
> > + bash -cx '[[ (( 100 < 3 )) ]] && echo ok'
> > + [[ 100 < 3 ]]
> > + echo ok
> The parentheses here are doubly redundant. You're performing a grouping,
> but there is only one operator, so there's nothing to group *for*. And
> you're doing the grouping twice, for no discernable reason.
> You're also using the < operator in a [[ ]] command, which is string
> comparison, not integer comparison.
> If your goal was simply "check whether the integer 100 is less than the
> integer 3", you don't need to use the [[ ]] command at all.
> if ((100 < 3)); then
> echo ok
> echo not ok
> If you insist on using [[ ]] for some reason, integer comparisons can be
> forced with the -lt -gt (et al.) operators.
> if [[ 100 -lt 3 ]]; then
> > bash -cx '[[ $(( 100 < 3 )) ]] && echo ok'
> > + bash -cx '[[ $(( 100 < 3 )) ]] && echo ok'
> > + [[ -n 0 ]]
> > + echo ok
> > ok
> Here, you are forcing an arithmetic substitution to be explicitly
> before the [[ ]] command begins. The result of the arithmetic substitution
> is a word, and that word will be checked for non-zero-length by the [[
> command. It is exactly as if you had written:
> tmp=$((100 < 3))
> [[ $tmp ]] && ...
> The form [[ $x ]] is just the same as [[ -n $x ]] and that's what you
> have written here.
> > bash -cx '[[ $(( 100 < 300 )) ]] && echo ok'
> > + bash -cx '[[ $(( 100 < 300 )) ]] && echo ok'
> > + [[ -n 1 ]]
> > + echo ok
> > ok
> Same. It doesn't matter whether the result of the arithmetic expression
> is 1 (true) or 0 (false), because both of these words are strings of
> non-zero length.
> To repeat: if your goal is to compare integers, you should use one of
> these forms:
> if ((x < y)); then ...
> if [[ $x -lt $y ]]; then ...
> if test "$x" -lt "$y"; then ...
> if [ "$x" -lt "$y" ]; then ...
> Remember, the [ and [[ commands are just that: *commands*. They are not
> a part of the "if" syntax. You don't *need* them every time you use
> an "if". You don't need to bend over backwards trying to work out how
> to merge the command you actually want to use, together with the [[
> Just omit the [[ if it's not the command you want.
INIAN VASANTH P