bug-bash
[Top][All Lists]
Advanced

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

Re: behavior of arithmetic evaluation operator inside extended test oper


From: Oğuz
Subject: Re: behavior of arithmetic evaluation operator inside extended test operator
Date: Tue, 19 May 2020 21:05:25 +0300

On Tue, May 19, 2020 at 8:36 PM Inian Vasanth <inian.vasanth@gmail.com> wrote:
>
> Thanks Greg for the explanation. Yes your explanation  aligns with my
> understanding too.
>
> My recommendation was to check if this behavior needs to be documented as a
> side-note in this section of
> http://www.gnu.org/savannah-checkouts/gnu/bash/manual/bash.html#Bash-Conditional-Expressions
> to
> explain that, any other primaries other than the ones mentioned above will
> be evaluated as a literal string result.

I don't think that's necessary, under `[[…]]`, it says

    Expressions may be combined using the following operators, listed
in decreasing order of precedence:

    ( expression )
        Returns the value of expression. This may be used to override
the normal precedence of operators.

With that it shouldn't be that hard to figure out `[[ (( x < y )) ]]`
equals to `[[ x < y ]]` in function.

> 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 <wooledg@eeg.ccf.org> wrote:
>
> > On Tue, May 19, 2020 at 06:10:30PM +0530, Inian Vasanth wrote:
> > > The behavior of arithmetic context operator $((..)) inside [[..]] is not
> > so
> > > 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
> > else
> >   echo not ok
> > fi
> >
> > 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
> > performed,
> > 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 [[
> > command.
> >
> > Just omit the [[ if it's not the command you want.
> >
>
>
> --
> Regards,
> INIAN VASANTH P



-- 
Oğuz



reply via email to

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