Search code examples
bashquoting

Parameters work properly when remove their quoting


I am puzzled about the verbose of quoting in the script. Take an example from the instruction I followed:

min_val=1
max_val=100
int=50
if [[ "$int" =~ ^-?[0-9]+$ ]]; then
    if [[ "$int" -ge "$min_val" &&  "$int" -le "$max_val" ]]; then
        echo "$int is within $min_val to $max_val."
    else
        echo "$int is out of range."
    fi
else
    echo "int is not an integer." >&2
    exit 1
fi

Run it and come by:

$ bash test_integer3.sh
50 is within 1 to 100.

When I removed all the quoting in testing:

if [[ $int =~ ^-?[0-9]+$ ]]; then
    if [[ $int -ge $min_val &&  $int -le $max_val ]]; then
        echo "$int is within $min_val to $max_val."
    else
        echo "$int is out of range."
    fi
else
    echo "int is not an integer." >&2
    exit 1
fi

It's still working properly.

$ bash test_integer3.sh
50 is within 1 to 100.

Why should live with the habit of writing redundant quoting?


Solution

  • The real problem comes when you start to use [ command over [[ in your scripts. [[ is bash's improvement to the [ command. It has several enhancements that make it a better choice to write scripts targeting bash.

    One such improvement would be that you no longer have to quote variables because [[ handles empty strings and strings with white-space more intuitively. For example consider your script written with [ for the un-quoted case and for discussions sake, one of your variables is empty

    #!/usr/bin/env bash
    
    min_val=
    max_val=
    int=50
    
    if [[ $int =~ ^-?[0-9]+$ ]]; then
        if [ $int -ge $min_val -a  $int -le $max_val ]; then
            echo "$int is within $min_val to $max_val."
        else
            echo "$int is out of range."
        fi
    else
        echo "int is not an integer." >&2
        exit 1
    fi
    

    One thing to note is I've re-written the combined conditional using the -a syntax since [ does not support && operator within but could be combined using && as [ $int -ge $min_val ] && [ $int -le $max_val ]

    You would see things going bad and seeing errors as below which means that one of the conditionals involving -le is gone wrong on seeing an empty string.

    1_script.sh: line 7: [: -a: integer expression expected
    50 is out of range.
    

    whereas with same code for undefined variables and replacing the expression to use [[ would gracefully handle the empty strings to produce just an incorrect result as

    50 is out of range.
    

    So to sum it up, from the many advantages over using [[, the particular advantage on your case is to handle variables if there could be empty strings in your conditionals.