3

Problem

I have to compare a string "problem1.sh" with itself. It works fine in case of solution1.sh (given below) where I have used square brackets for comparison. However, it does not work in case of solution2.sh (given below) where I have used round brackets. It shows the mentioned error (given below).

What I have tried?

I have tried to learn the difference between the use of square and round brackets in bash script from here and here. I understand that ((expression)) is used for comparison arithmetic values, not for the string values.

What creates the problem?

If I remove sub-string ".sh" from the string "problem1.sh" and compare using the same statement if (("problem1" == "problem1")), it works fine. However, when I just add "." in the string, it creates the problem. Even if I remove everything except "." from the string and use the statement if (("." == ".")), it shows me error.

My Question

If the statement if (("problem1" == "problem1")) can work fine (may be, it will work fine for every letter of English alphabet), why does "." string create the problem? I mean, Why we can not compare "." using round brackets in if statement of bash script (e.g if (("." == "."))) when we can compare letters using the same expression (e.g if (("findError" == "findError"))) ?

solution1.sh

if [ "problem1.sh" == "problem1.sh" ]
then
        printf "Okay"   
fi

solution2.sh

if (( "problem1.sh" == "problem1.sh" ))
then
        printf "Okay"   
fi

Error Message For solution2.sh

./solution2.sh: line 1: ((: problem1.sh == problem1.sh : syntax error:
    invalid arithmetic operator (error token is ".sh == problem1.sh ")
  • 1
    Why are you using strings in an arithmetic evaluation (((...)))? What is it you want to actually do? – Kusalananda Nov 17 '19 at 14:43
  • 2
    Why not just use [[ ]]? (( )) is for artihmetic operations so why do you need that one? You can even do arithmetic operations inside of [ ] or [[ ]] if you use -eq, lt, gt, lte, or gte. – Nasir Riley Nov 17 '19 at 14:49
  • @Nasir Riley, I do not need to use (( )). Rather, I need to know why dot does not work when the letters work? – Md. Sabbir Ahmed Nov 17 '19 at 14:54
  • @Kusalananda In the description, I have tried my best to clarify my question. If I fail to make understand you, I am extremely sorry for that. – Md. Sabbir Ahmed Nov 17 '19 at 14:58
  • 3
    If you understand that ((...)) is for arithmetic evaluation, then why are you trying to compare strings using this? In your example problem1 will be taken as a variable's name. If that variable is unset, the value used will be 0 (or possibly empty, one or the other, integer evaluation is weird). When you add .sh you introduce nonsense into the expression (0.sh (or .sh) is not a valid integer expression). I still don't know what it is you are trying to do. – Kusalananda Nov 17 '19 at 15:01
5

There is a problem in the translation of languages.
In the arithmetic expression language a dot doesn't exist.

You are using a language that can not work inside a "$((…))".

Inside "$((…))" (an arithmetic expression) there could be only numbers (usually integers like 1234), operators (+, -, *, << and yes == as equality operator, among others), and variables (one or more letters, numbers (not the first character) and underscores). That's all. There is no concept of string.

When you write problem1 inside an arithmetic expression it is understood in that language as a variable name (with value 0 if not previously defined):

$ echo "==$((problem1))=="
==0==

$ problem1=34
$ echo "==$((problem1))=="
==34==

It doesn't matter if the text is inside quotes:

$ echo "==$(("problem1"))=="
==34==

What you are using, the ((…)) is also an Arithmetic Expression which just happens to have no output. It just sets the exit status (and, as in C, it is true if the result of the expression is not 0).

$ (( 1 + 1 ))  ; echo "$?"
0
$ (( 0 ))      ; echo "$?"
1
$ (( 1 - 10 )) ; echo "$?"
0

But an arithmetic expression doesn't understand what a dot is, neither as an operator nor as a variable name, so, it generates a syntax error:

$ echo "$(( 1.3 ))"
bash: 1.3 : syntax error: invalid arithmetic operator (error token is ".3 ")

The same also apply to a variable name (problem1) followed by a dot and followed by another variable name (sh).

$ echo "$((problem1.sh))"
bash: problem1.sh: syntax error: invalid arithmetic operator (error token is ".sh")

If the operator were a + instead of a dot, the expression would work:

$ echo "$((problem1+sh))"
34

If problem1 has been set to 34 (as above).

So, the only way to compare strings is to use [[…]]:

$ [[ problem1.sh == problem1.sh ]] && echo YES
YES

(not quoting the right side of == in this particular case as there is no variable expansion and the string has no glob characters, but in general, do quote the string on the right side of the ==).

Or, similar to what you wrote:

if       [[ "problem1.sh" == "problem1.sh" ]]
then     printf "Okay"   
fi
2

As you suspect, (( == )) compares two numeric values. But inside those (( )), for convenience, you can also just write variable names -- you don't have to say $VAR, just VAR.

Also note, the error message does not contain the quotes. I'm mildly surprised at that. Actually, no -- the parser inspects it for substitutions, then passes the word with quotes removed.

Nevertheless, I believe the parser is quite happy to accept problem1 as a variable name, until it hits the .; so it reports the text it can't understand, starting at ".sh".

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.