• Uncategorized

About bash : Check-whether-one-number-equals-another-number-in-Bash

Question Detail

I’ve been trying to compare whether two numbers in Bash are equal (and print a message if they are equal), but I’m getting some strange error messages for this simple program:

fun2 (){
$x = 3
//#prog.sh: line 4: =: command not found
if [x == 3]
//#prog.sh: line 6: [x: command not found
echo “It’s 3!”

The corresponding errors are shown below the lines that caused those errors.

Question Answer

It must be:
if [ $x -eq 3 ]; then …..

If you prefer a more readable and self-explanatory code, use this syntax:
if test $x -eq 3; then …..

To compare integers you must use those operators (copied from man test):
INTEGER1 is equal to INTEGER2

INTEGER1 is greater than or equal to INTEGER2

INTEGER1 is greater than INTEGER2

INTEGER1 is less than or equal to INTEGER2

INTEGER1 is less than INTEGER2

INTEGER1 is not equal to INTEGER2

operators == and != are for string comparison only.
For information: “[” command is an alias for system “test” command.
Shell scripting wasn’t really meant to be a full language, and it is heavily dependent upon other external commands to work.
Variables use a sigil which is that $ in front of them. A lot of shell scripting languages use variable sigils to help distinguish between a string and a variable.
For example:
echo foo foo $foo foo

Will print:
foo foo foo_value foo

Note that quotes are not necessary for the echo statement for strings. Windows Batch shell is very similar:
set foo = foo_value
echo foo foo %foo% foo

As you can see, the sigil is used when the variable is supposed to be expanded, but not when you define it. That’s because Unix shells are intelligent shells. They munge the command line before it is even executed. The shell will substitute the environment variables before execution:
$foo=”whose value is this” # Note the dollar sign!
echo The value of foo is $foo
echo The value of bar is $bar

This will print out:
The value of foo is foo
The value of bar is whose value is this

If you use the set -xv command, you’ll see that $foo=”whose value is this” is expanded to bar=whose value is this” before it is executed.
In Bourne style shells like KornShell and Bash, the if statement isn’t what you think it is. The if command executes the statement, and will select the if clause if that command returns a zero value. For example:
cat “foo” > my_file # Create a one line file with the string foo in it.
if grep -q “foo” my_file # grep command will return a zero exit code if it finds foo
echo “The string ‘foo’ is in file my_file”

Notice that the if clause isn’t a Boolean statement. It’s an actual command that is executed.
Somewhere early in Unix development, the test command was created. You can do a man test and see how to use it.
The test command allows you to do this:
if test foo -eq bar
echo “foo and bar are equal”
echo “foo and bar are not equal”

If you do this:
$ ls -li /bin/test /bin/[

You will see that a command called [ actually exists, and is a hard link to the test command. This was created to make an if statement look more like a if statement you’ll see in regular programming languages:
if [ foo -eq bar ]
echo “foo and bar are equal”
echo “foo and bar are not equal”

It is the exact same script as above, but with [ instead of test.
This explains why you need the dash in many tests (it’s a parameter to the test command, and parameters start with a dash!). It also explains why you need spaces around the [ and ]. These are actual Unix commands, and Unix commands must have white spaces around them, so the shell can process them.
Another issue is: Why does the shell have two different sets of tests for strings and numbers? That’s because strings may contain nothing but digits, but are not really numeric. For example, if you do inventory, you might have a part number 001 and 01. Numerically, they’re equal, but as strings, they’re two different strings. There is no way for the shell script to know. Instead, you must let the shell script know if it’s a numeric comparison or a string comparison.
Perl has similar issues since you don’t declare variables as numeric or non-numeric:
Shell Script Perl
Boolean Operator Numeric String Numeric String
=================== ======= ====== ======= ======
Equals -eq = == eq
Not Equals -ne != != ne
Greater Than -gt > > gt
Less Than -lt < < lt Greater or Equals -ge >= >= ge
Less Than or Equals -le <= <= le You can try a few other things: $ echo "*" # Echos the asterisk $ echo * # No quotes: Prints all files in current directory Notice again the shell expands the * before executing the echo command. This is the main difference between a shell script and a typical programming language. The shell first does expansion (fill in environment variables, glob substitution, and run sub-commands) before it actually executes the command. The set -xv will show you what command is being executed, and how the shell expands the command before executing. Doing set +xv will shut that off. Play around with that, and you'll soon understand the shell a bit better. ............................................................ For the first error message, remove the dollar sign $ and no spaces are allowed around the equal sign = x=3 For the second error message, insert a space and a dollar sign $ before x and a space after 3 if [ $x -eq 3 ] As loentar correctly pointed out, it must be -eq and neither = nor ==. ............................................................ the spaces are mandatory in the [ ] expression, so if [ $x == 3 ]; then you need a sigill on variables in the [ ] tests ............................................................ For clarity, use == for equality rather than = even though both work. The former encourages the use of [[ and the latter can be confused with an assignment. Use (( … )) or -lt and -gt for numerical comparison. if [[ "${my_var}" == "val" ]]; then do_something fi if (( my_var == 3 )); then do_something fi if [[ "${my_var}" -gt 3 ]]; then do_something fi

You may also like...

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.