1

I have written below script:

#!/usr/bin/bash

STR_1="nfosys" STR_2="Infosys"

if (( $STR_1 == $STR_2 )) then echo "Strings are equal" else echo "Strings are not equal" fi

Getting Output:

root:~/Desktop/user_repo/Demo# bash -x test.sh 
+ STR_1=nfosys
+ STR_2=Infosys
+ ((  nfosys == Infosys  ))
+ echo 'Strings are equal'
Strings are equal
root:~/Desktop/user_repo/Demo# 

Ideally it should print "Strings are not equal" statment but i am unable to understand why it is printing "Strings are equal"

Poonam
  • 91

3 Answers3

7

(( .. )) is an arithmetic construct, and in arithmetic contexts, a string is taken as the name of a variable, and the value of that variable is used. This happens after $var expansions are expanded, so your script looks at variables called nfosys and Infosys. With both variables unset, both are taken to be zero, i.e. equal. But:

$ str1=foo str2=bar foo=1
$ (( $str1 == $str2 )) && echo true || echo false
false   

See e.g. Bash's manual on shell arithmetic:

Shell variables are allowed as operands; parameter expansion is performed before the expression is evaluated. Within an expression, shell variables may also be referenced by name without using the parameter expansion syntax. A shell variable that is null or unset evaluates to 0 when referenced by name without using the parameter expansion syntax.

For string comparison, use

[ "$STR_1" = "$STR_2" ]   # in any POSIX shell, or

[[ $STR_1 = "$STR_2" ]] # in Bash/ksh/zsh

The former needs quotes due to word-splitting, the latter needs it only on the right-hand side (in bash / ksh) for $STR_2 not to be taken as a pattern.

Also see: What is the difference between the Bash operators [[ vs [ vs ( vs ((?

ilkkachu
  • 138,973
1

Using [] instead would give the wanted behavior:

STR_1="nfosys"
STR_2="Infosys"

if [ $STR_1 = $STR_2 ] then echo "Strings are equal" else echo "Strings are not equal" fi

Output:

+ STR_1=nfosys
+ STR_2=Infosys
+ '[' nfosys = Infosys ']'
+ echo 'Strings are not equal'
Strings are not equal

A good rule of thumb is to also quote your variables, just in case they end up being wrongly interpreted or be expanded/split:

STR_1="nfosys"
STR_2="Infosys"

if [ "$STR_1" = "$STR_2" ] then echo "Strings are equal" else echo "Strings are not equal" fi

Also, while [] is considered POSIX, using [[]] if your main target is bash, is better.

Editor's note: POSIX only knows single =.

  • I tried using above but getting below message -test.sh: 6: [[: not found – Poonam Mar 27 '22 at 15:50
  • if i use single bracket then getting message -test.sh: 6: [: nfosys: unexpected operator – Poonam Mar 27 '22 at 15:52
  • 1
    this is weird. How did you run your script? @Poonam – Nordine Lotfi Mar 27 '22 at 15:55
  • 1
    Also, thanks for the editor's note ;) I forgot to take this into account – Nordine Lotfi Mar 27 '22 at 16:06
  • @Poonam Pass the script through shellcheck.net. I suspect you have combined parts of several different answers. – Paul_Pedant Mar 27 '22 at 16:18
  • Why show that [ $STR_1 = $STR_2 ] (without the quotes) at all? That's very wrong and a command injection vulnerability in shells such as bash. [ $STR_1 = $STR_2 ] should be an example of something not to do. – Stéphane Chazelas Mar 27 '22 at 17:43
  • that's true, but I only showed that to emphasize that "this work as it is if you just use [ instead of..." by reusing their own stated example :) And yes, I didn't take into account code injection but I did said quoting was a good rule of thumb and what not @StéphaneChazelas – Nordine Lotfi Mar 27 '22 at 17:58
0

Thanks All. i have restarted my session and change to single square bracket -

#!/usr/bin/bash

STR_1="nfosys" STR_2="Infosys"

if [ $STR_1 == $STR_2 ] then echo "Strings are equal" else echo "Strings are not equal" fi

If i execute with sh test.sh then getting error -

root@ip:~# sh test.sh 
test.sh: 6: [: nfosys: unexpected operator
Strings are not equal
root@ip:~# bash test.sh 
Strings are not equal

If i execute with bash then display correct output without any error

root@ip:~# bash test.sh 
Strings are not equal

Weird before posting question i had tried both ways - sh/bash and with ()/[]. But after restarting session seems working fine.


Editor's refreshed code adhering to POSIX, and some good codex (lower-case variable names, error print to stderr, fixed major == issue, etc.):

#!/bin/sh

str_1=nfosys str_2=Infosys

if [ "$str_1" = "$str_2" ]; then echo "Strings are equal" else echo "Strings are not equal" >&2 exit 1 fi

Poonam
  • 91
  • 1
    I hope you won't mind some good advice, feel free to edit it... Cheers, and good luck with Bash/shell in general. – Vlastimil Burián Mar 27 '22 at 17:28
  • 1
    [ $STR_1 == $STR_2 ] is very wrong even with bash. It even introduces a command injection vulnerability in bash. That's because of the missing quotes, not the == instead of = in that case. Try if you dare after STR_1='-v a[$(reboot)] -o x' STR_2=x for instance. – Stéphane Chazelas Mar 27 '22 at 17:47