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 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 <wool...@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