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?

4
  • 1
    If the number is always integer, why don't you just abs=${val#-}?
    – choroba
    Apr 17, 2015 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. Apr 17, 2015 at 15:34
  • 2
    @syntaxerror; note that (not all but) this sort of variable expansion is even defined in POSIX.
    – Janis
    Apr 17, 2015 at 15:42
  • 1
    It may be noteworthy that ksh supports abs(x) in arithmetic contexts.
    – Janis
    Apr 17, 2015 at 15:51

1 Answer 1

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" ]].

4

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.