1

This snippet of code has been taken from a larger script, (humbly) simulating the non-existing abs() function:

[[ $(echo "$val < 0" | bc) -eq 1 ]] && val=$(echo "$val * -1" | bc)

So we test the number whether it is negative; if yes the second statement after the && will be executed. This was my original line.

Some other SE user later changed this into:

(( $(bc <<<"$val < 0") == 1 )) && val=$(bc <<<"$val * -1")

OK, though both of these apparently work, I still prefer mine as it does not only make use of the -eq operator (which has been implemented especially for non-strings) but it also avoids here-strings, which makes the code work better on read-only environments. (Keep in mind that /tmp MUST be writeable for here-strings to work.)

Lastly, I seem to remember that bc in the later line will output a true integer, which makes the use of == rather questionable, since this is only recommended to be used for strings. Unfortunately bc does not reveal in its man page either whether it outputs its results as plain numbers or strings.

Opinions?

syntaxerror
  • 2,246
  • 1
    If the number is always integer, why don't you just abs=${val#-}? – choroba Apr 17 '15 at 15:33
  • Just never thought of that, thanks for the inspiration. :) I'm a bash old-schooler and still not too familiar with the "modern" ${...#...} syntax using brace substitution. – syntaxerror Apr 17 '15 at 15:34
  • 2
    @syntaxerror; note that (not all but) this sort of variable expansion is even defined in POSIX. – Janis Apr 17 '15 at 15:42
  • 1
    It may be noteworthy that ksh supports abs(x) in arithmetic contexts. – Janis Apr 17 '15 at 15:51

1 Answers1

2

You have confused here.

Both [[ $(echo "$val < 0" | bc) -eq 1 ]] and (( $(bc <<<"$val < 0") == 1 )) used integer comparison.

((..)) is equivalent to let builtin in ksh, bash and zsh. It evaluated arithmetic expression. Inside ((..)), all operators and their precedence, associativity, and values are the same as in the C language.

The one make you confuse was == inside new test operator [[...]]. When == available, it's equivalent with = and perform pattern matching. You need to double quotes either sides for doing string comparison [[ "$a" == "$b" ]].

cuonglm
  • 153,898
  • Well, thanks for the explanation, but in fact I didn't "confuse" anything. I simply was unsure, hence I chose to ask. Plus, I wasn't able to determine the bc output type. Whatever, in the bash manual page, there was nothing written explicitly about the == being used for numbers - only for strings. – syntaxerror Apr 17 '15 at 15:57
  • 1
    @syntaxerror: You have confused with == in ((..)) and == in [[...]]. Inside ((..)), == is arithmetic operator, it performed integer comparison. I invite you to read http://unix.stackexchange.com/q/149823/38906 – cuonglm Apr 17 '15 at 15:59
  • Can we agree that the manual is a bit too less clear and verbose on this matter still? ;) – syntaxerror Apr 17 '15 at 16:02
  • @syntaxerror: It has documented clearly. See: http://www.gnu.org/software/bash/manual/bash.html#Conditional-Constructs and http://www.gnu.org/software/bash/manual/bash.html#Shell-Arithmetic – cuonglm Apr 17 '15 at 16:11