Confused with (Bash) Shell Script Tests?

Run this:

#!/bin/bash

#########################################################################################
#                                                                                       #
#  BASH SHELL TEST FUNCTIONS DEMONSTRATION                                              #
#  (c) 2009 Edwards Research Group                                                      #
#           www.edwards-research.com                                                    #
#  Released under a Creative Commons Attribution-Share Alike 3.0 United States License  #
#                                                                                       #
#########################################################################################

# Notes:
# --Page 2 and 3 have functions commented out for two reasons, either
#   a) they produce an unexpected result, or
#   b) they are very prone to throwing errors (possibly by incorrect variable type,
#       or they don't handle null values well, etc) and there is another syntax that
#       is more error-resistant.
#   In both cases there are notes in the right hand comment section about why they
#    are commented out.  Of course, feel free to remove the comment marks and play
#    around to judge for yourself.
#

# Revision History:
#   2009-10-07    0.1    Initial Release
#

red='\033[0;31;40m'
green='\033[0;32;40m'
blue='\033[0;34;40m'

rst='\033[0m'

function crst()
{
        tput sgr0
}

function cecho()
{
        # $1 = msg
        # $2 = color
        # cecho "Jim is cool" $bold"

        echo -ne "${2}"
        echo -e  "${1}"
        echo -ne "${rst}"
        crst
}

function init()
{
  clear
  cecho "BASH SHELL SCRIPT LOGIC DEMONSTRATION                    " ${blue}
  echo  "This demo has 5 parts:                                   "
  echo  "  1. Shell Arguments / Parameters and Variable Expansion "
  echo  "  2. String and Integer Equality                         "
  echo  "  3. String and Integer Comparison                       "
  echo  "  4. Single Variable Binary Tests                        "
  echo  "  5. File / Directory Tests (coming soon)                "
  echo  "                                                         "
        echo  "You may pick a single page by entering the page number   "
        echo  "at this prompt, or to see them all, press any other key. "
  echo  "To advance each section, press any key at the prompt     "
  echo -n "..." ; read JUMP
}

function page1()
{
  clear
  cecho "Shell Arguments:                     " ${blue}
  cecho "Entire Argument Line                 " ${red}
  echo '    "$@"  ' "$@"
  echo '     $@   ' $@
  echo '    "$*"  ' "$*"
  echo '     $*   ' $*
  cecho "Number of Arguments (Space Separated)" ${red}
  echo '    "$#"  ' "$#"
  echo '     $#   ' $#
  cecho "Path and Name of Current Script      " ${red}
  echo '    "$0"  ' "$0"
  echo '     $0   ' $0
  cecho "First Argument                       " ${red}
  echo '    "$1"  ' "$1"
  echo '     $1   ' $1
  if [[ ${SET_PROMPT} ]] ; then echo -n "..." ; read ; fi
}

function page2()
{
  clear
  cecho "Equality Tests" ${blue}
  echo  '  Use argument #1 and #2 to change the values of the tests, which '
  echo  '  can be seen by viewing the source.                              '
  echo  '    $1 is compared to a string ("Jim")                            '
  echo  '    $2 is compared to an integer (2)                              '
  echo  '  Only when tests evaluate to true are their test numbers printed.'
  echo  '                                                                  '
  echo  '                                                                  '
  cecho "String Equality:" ${red}
  #if [ $1 == "Jim" ] ;      then echo "1" ; fi     # Error on null
  if [ "$1" == "Jim" ] ;    then echo '2' ; fi      #
  #if [ $1 = "Jim" ] ;       then echo "3" ; fi     # Error on null
  if [ "$1" = "Jim" ] ;     then echo "4" ; fi      #
  #if [ $1 -eq "Jim" ] ;     then echo "5" ; fi     # Always Errors (Int Exp Expected)
  #if [ "$1" -eq "Jim" ] ;   then echo "6" ; fi     # Always Errors (Int Exp Expected)
  if [[ $1 == "Jim" ]] ;    then echo "7" ; fi      #
  if [[ "$1" == "Jim" ]] ;  then echo "8" ; fi      #
  if [[ $1 = "Jim" ]] ;     then echo "9" ; fi      #
  if [[ "$1" = "Jim" ]] ;   then echo "A" ; fi      #
  #if [[ $1 -eq "Jim" ]] ;   then echo "B" ; fi     # Always True
  #if [[ "$1" -eq "Jim" ]] ; then echo "C" ; fi     # Always True
  echo
  cecho "Integer Equality:" ${red}
  #if [ $2 == 2 ] ;      then echo "0" ; fi         # Error on null
  if [ "$2" == 2 ] ;    then echo "1" ; fi          #
  #if [ $2 = 2 ] ;       then echo "2" ; fi         # Error on null
  if [ "$2" = 2 ] ;     then echo "3" ; fi          #
  #if [ $2 -eq 2 ] ;     then echo "4" ; fi         # Error on null, Error when not int
  #if [ "$2" -eq 2 ] ;   then echo "5" ; fi         # Error when not int
  if [[ $2 == 2 ]] ;    then echo "6" ; fi          #
  if [[ "$2" == 2 ]] ;  then echo "7" ; fi          #
  if [[ $2 = 2 ]] ;     then echo "8" ; fi          #
  if [[ "$2" = 2 ]] ;   then echo "9" ; fi          #
  #if [[ $2 -eq 2 ]] ;   then echo "A" ; fi         # Fail (4)
  #if [[ "$2" -eq 2 ]] ; then echo "B" ; fi         # Fail (4)
  if [[ ${SET_PROMPT} ]] ; then echo -n "..." ; read ; fi
}

function page3()
{
  clear
  cecho "Comparisons:" ${blue}
  echo "The numbers printed correspond to different tests that were run in"
  echo "  the script.  If the number was printed, the test evaluated to true"
  cecho "String Comparison:" ${red}
  #if [ $1 > "Jim" ] ;       then echo "0" ; fi     # Doesn't evaluate correctly (1)
  #if [ "$1" > "Jim" ] ;     then echo "1" ; fi                 # Doesn't evaluate correctly (1)
  #if [ $1 < "Jim" ] ;       then echo "2" ; fi     # Doesn't evaluate correctly (1)
  #if [ "$1" < "Jim" ] ;     then echo "3" ; fi     # Doesn't evaluate correctly (1)
  #if [ $1 -gt "Jim" ] ;     then echo "4" ; fi     # Always Errors
  #if [ "$1" -gt "Jim" ] ;   then echo "5" ; fi     # Always Errors
  #if [ $1 -lt "Jim" ] ;     then echo "6" ; fi     # Always Errors
  #if [ "$1" -lt "Jim" ] ;   then echo "7" ; fi     # Always Errors
  if [[ $1 > "Jim" ]] ;     then echo "8" ; fi      #
  if [[ "$1" > "Jim" ]] ;   then echo "9" ; fi      #
  if [[ $1 < "Jim" ]] ;     then echo "A" ; fi      #
  if [[ "$1" < "Jim" ]] ;   then echo "B" ; fi      #
  #if [[ $1 -gt "Jim" ]] ;   then echo "C" ; fi     # Fail: Non-alpha (4) Note (5)
  #if [[ "$1" -gt "Jim" ]] ; then echo "D" ; fi     # Fail: Non-alpha (4) Note (5)
  #if [[ $1 -lt "Jim" ]] ;   then echo "E" ; fi     # Fail: Non-alpha (4) Note (6)
  #if [[ "$1" -lt "Jim" ]] ; then echo "F" ; fi     # Fail: Non-Alpha (4) Note (6)
  echo
  cecho "Integer Comparison:" ${red}
  #if [ $2 > 2 ] ;       then echo "0" ; fi         # Doesn't evaulate correctly (1)
  #if [ "$2" > 2 ] ;     then echo "1" ; fi                                   # Doesn't evaluate correctly (1)
  #if [ $2 < 2 ] ;       then echo "2" ; fi         # Doesn't evaulate correctly (1)
  #if [ "$2" < 2 ] ;     then echo "3" ; fi         # Doesn't evaulate correctly (1)
  if [ $2 -gt 2 ] ;     then echo "4" ; fi          # Error when not int (8)
  if [ "$2" -gt 2 ] ;   then echo "5" ; fi          # Error when not int (8)
  if [ $2 -lt 2 ] ;     then echo "6" ; fi          # Error when not int (8)
  if [ "$2" -lt 2 ] ;   then echo "7" ; fi          # Error when not int (8)
  #if [[ $2 > 2 ]] ;     then echo "8" ; fi         # Fail: Eval String (7)
  #if [[ "$2" > 2 ]] ;   then echo "9" ; fi         # Fail: Eval String (7)
  #if [[ $2 < 2 ]] ;     then echo "A" ; fi         # Fail: Eval String (7)
  #if [[ "$2" < 2 ]] ;   then echo "B" ; fi         # Fail: Eval String (7)
  if [[ $2 -gt 2 ]] ;   then echo "C" ; fi          # Note: Non-alpha (4) Note (3)
  if [[ "$2" -gt 2 ]] ; then echo "D" ; fi          # Note: Non-alpha (4) Note (3)
  if [[ $2 -lt 2 ]] ;   then echo "E" ; fi          # Note: Non-alpha (4) Note (3)
  if [[ "$2" -lt 2 ]] ; then echo "F" ; fi          # Note: Non-alpha (4) Note (3)
  echo

  cecho "Notes:                                                 " ${red}
  echo "   (1)  If Variable is set, always evaluates to true    "
  echo "        If Variable is unset, always evaluates to false "
  echo "   (2)  Wildcards in the string (eg 'a*') will throw    "
  echo "        an error.                                       "
  echo "   (3)  If passed a string, it may attempt to convert   "
  echo "        the string to an integer, possibly throwing an  "
  echo "        error.                                          "
  echo "   (4)  A non-alphanumeric character throws an error.   "
  echo "   (5)  If an integer is passed, it equals true.        "
  echo "   (6)  This never evaluates to true.                   "
  echo "   (7)  This doesn't evaluate as expected, it does a    "
  echo "        character-wise comparison, like comparing a     "
  echo "        string.                                         "
  echo "   (8)  This will throw an error if any non-integer is  "
  echo "        passed -- consider [[ ]] for casting alpha-     "
  echo "        numeric integer formats                         "
  if [[ ${SET_PROMPT} ]] ; then echo -n "..." ; read ; fi
}

function page4()
{
  ISET=1
  ZERO=0
  ZLEN=""
  RLEN="Jim"
  #NULL

  clear
  cecho "Binary Tests" ${blue}
  echo 'Parameters:    ${ISET} = 1               - 1 (Numeral One)           '
  echo '               ${ZERO} = 0               - 0 (Numeral Zero)          '
  echo '               ${ZLEN} = ""              - Zero Length String        '
  echo '               ${RLEN} = "Jim"           - Nonzero Length String     '
  echo '               ${BULL} (never set)       - Unset Variable Reference  '
  echo
  echo '  ** If a test evaluated to true, it has been printed **             '
  cecho "Operator [ -z ]" ${red}                                       # False unless specified
  if  [ -z  ${ISET}  ]  ; then echo '    [  -z  ${ISET}   ]' ; fi      #
  if  [ -z "${ISET}" ]  ; then echo '    [  -z "${ISET}"  ]' ; fi      #
  if  [ -z  ${ZERO}  ]  ; then echo '    [  -z  ${ZERO}   ]' ; fi      #
  if  [ -z "${ZERO}" ]  ; then echo '    [  -z "${ZERO}"  ]' ; fi      #
  if  [ -z  ${ZLEN}  ]  ; then echo '    [  -z  ${ZLEN}   ]' ; fi      # True
  if  [ -z "${ZLEN}" ]  ; then echo '    [  -z "${ZLEN}"  ]' ; fi      # True
  if  [ -z  ${RLEN}  ]  ; then echo '    [  -z  ${RLEN}   ]' ; fi      #
  if  [ -z "${RLEN}" ]  ; then echo '    [  -z "${RLEN}"  ]' ; fi      #
  if  [ -z  ${NULL}  ]  ; then echo '    [  -z  ${NULL}   ]' ; fi      # True
  if  [ -z "${NULL}" ]  ; then echo '    [  -z "${NULL}"  ]' ; fi      # True
  cecho "Operator [[ -z ]]" ${red}                                     # ----
  if [[ -z  ${ISET}  ]] ; then echo '    [[ -z  ${ISET}  ]]' ; fi      #
  if [[ -z "${ISET}" ]] ; then echo '    [[ -z "${ISET}" ]]' ; fi      #
  if [[ -z  ${ZERO}  ]] ; then echo '    [[ -z  ${ZERO}  ]]' ; fi      #
  if [[ -z "${ZERO}" ]] ; then echo '    [[ -z "${ZERO}" ]]' ; fi      #
  if [[ -z  ${ZLEN}  ]] ; then echo '    [[ -z  ${ZLEN}  ]]' ; fi      # True
  if [[ -z "${ZLEN}" ]] ; then echo '    [[ -z "${ZLEN}" ]]' ; fi      # True
  if [[ -z  ${RLEN}  ]] ; then echo '    [[ -z  ${RLEN}  ]]' ; fi      #
  if [[ -z "${RLEN}" ]] ; then echo '    [[ -z "${RLEN}" ]]' ; fi      #
  if [[ -z  ${NULL}  ]] ; then echo '    [[ -z  ${NULL}  ]]' ; fi      # True
  if [[ -z "${NULL}" ]] ; then echo '    [[ -z "${NULL}" ]]' ; fi      # True
  cecho "Operator [ -n ]" ${red}                                       # ----
  if  [ -n  ${ISET}  ]  ; then echo '    [  -n  ${ISET}   ]' ; fi      # True
  if  [ -n "${ISET}" ]  ; then echo '    [  -n "${ISET}"  ]' ; fi      # True
  if  [ -n  ${ZERO}  ]  ; then echo '    [  -n  ${ZERO}   ]' ; fi      # True
  if  [ -n "${ZERO}" ]  ; then echo '    [  -n "${ZERO}"  ]' ; fi      # True
  if  [ -n  ${ZLEN}  ]  ; then echo '    [  -n  ${ZLEN}   ]' ; fi      # True
  if  [ -n "${ZLEN}" ]  ; then echo '    [  -n "${ZLEN}"  ]' ; fi      #
  if  [ -n  ${RLEN}  ]  ; then echo '    [  -n  ${RLEN}   ]' ; fi      # True
  if  [ -n "${RLEN}" ]  ; then echo '    [  -n "${RLEN}"  ]' ; fi      # True
  if  [ -n  ${NULL}  ]  ; then echo '    [  -n  ${NULL}   ]' ; fi      # True
  if  [ -n "${NULL}" ]  ; then echo '    [  -n "${NULL}"  ]' ; fi      #
  cecho "Operator [[ -n ]]" ${red}                                     # ----
  if [[ -n  ${ISET}  ]] ; then echo '    [[ -n  ${ISET}  ]]' ; fi      # True
  if [[ -n "${ISET}" ]] ; then echo '    [[ -n "${ISET}" ]]' ; fi      # True
  if [[ -n  ${ZERO}  ]] ; then echo '    [[ -n  ${ZERO}  ]]' ; fi      # True
  if [[ -n "${ZERO}" ]] ; then echo '    [[ -n "${ZERO}" ]]' ; fi      # True
  if [[ -n  ${ZLEN}  ]] ; then echo '    [[ -n  ${ZLEN}  ]]' ; fi      #
  if [[ -n "${ZLEN}" ]] ; then echo '    [[ -n "${ZLEN}" ]]' ; fi      #
  if [[ -n  ${RLEN}  ]] ; then echo '    [[ -n  ${RLEN}  ]]' ; fi      # True
  if [[ -n "${RLEN}" ]] ; then echo '    [[ -n "${RLEN}" ]]' ; fi      # True
  if [[ -n  ${NULL}  ]] ; then echo '    [[ -n  ${NULL}  ]]' ; fi      #
  if [[ -n "${NULL}" ]] ; then echo '    [[ -n "${NULL}" ]]' ; fi      #

        # Disable prompt at the last page
        #if [[ ${SET_PROMPT} ]] ; then echo -n "..." ; read ; fi
}

function page5()
{
        # Not yet implemented.
        DUMMY=1 # So bash won't whine about an empty function
}

init

# Sanitize Input
START_PAGE=$( echo "${JUMP}" | tr -cd '[:digit:]' )

# Make PAGE=0 as default (all pages)
if [ -z ${START_PAGE} ] ; then
        START_PAGE=0
        SET_PROMPT=1
fi

case ${START_PAGE} in
0)
        page1 "$@"
        page2 "$@"
        page3 "$@"
        page4 "$@"
        page5 "$@"
        ;;
1)
        page1   "$@";;
2)
        page2   "$@";;
3)
        page3 "$@";;
4)
        page4 "$@";;
5)
        page5 "$@";;
*)
        echo "?" ; exit ;;
esac

echo "Script Complete - Exiting."

Running the script with: ./test testing 7 results in:

BASH SHELL SCRIPT LOGIC DEMONSTRATION
This demo has 5 parts:
  1. Shell Arguments / Parameters and Variable Expansion
  2. String and Integer Equality
  3. String and Integer Comparison
  4. Single Variable Binary Tests
  5. File / Directory Tests (coming soon)

You may pick a single page by entering the page number
at this prompt, or to see them all, press any other key.
To advance each section, press any key at the prompt
...

Page 1:

Shell Arguments:
Entire Argument Line
    "$@"   testing 7
     $@    testing 7
    "$*"   testing 7
     $*    testing 7
Number of Arguments (Space Separated)
    "$#"   2
     $#    2
Path and Name of Current Script
    "$0"   /root/test.sh
     $0    /root/test.sh
First Argument
    "$1"   testing
     $1    testing
...

Page 2:

Equality Tests
  Use argument #1 and #2 to change the values of the tests, which
  can be seen by viewing the source.
    $1 is compared to a string ("Jim")
    $2 is compared to an integer (2)
  Only when tests evaluate to true are their test numbers printed.

String Equality:

Integer Equality:
...

Page 3:

Comparisons:
The numbers printed correspond to different tests that were run in
  the script.  If the number was printed, the test evaluated to true
String Comparison:
8
9

Integer Comparison:
4
5
C
D

Notes:
   (1)  If Variable is set, always evaluates to true
        If Variable is unset, always evaluates to false
   (2)  Wildcards in the string (eg 'a*') will throw
        an error.
   (3)  If passed a string, it may attempt to convert
        the string to an integer, possibly throwing an
        error.
   (4)  A non-alphanumeric character throws an error.
   (5)  If an integer is passed, it equals true.
   (6)  This never evaluates to true.
   (7)  This doesn't evaluate as expected, it does a
        character-wise comparison, like comparing a
        string.
   (8)  This will throw an error if any non-integer is
        passed -- consider [[ ]] for casting alpha-
        numeric integer formats
...

Page 4:

Binary Tests
Parameters:    ${ISET} = 1               - 1 (Numeral One)
               ${ZERO} = 0               - 0 (Numeral Zero)
               ${ZLEN} = ""              - Zero Length String
               ${RLEN} = "Jim"           - Nonzero Length String
               ${BULL} (never set)       - Unset Variable Reference

  ** If a test evaluated to true, it has been printed **
Operator [ -z ]
    [  -z  ${ZLEN}   ]
    [  -z "${ZLEN}"  ]
    [  -z  ${NULL}   ]
    [  -z "${NULL}"  ]
Operator [[ -z ]]
    [[ -z  ${ZLEN}  ]]
    [[ -z "${ZLEN}" ]]
    [[ -z  ${NULL}  ]]
    [[ -z "${NULL}" ]]
Operator [ -n ]
    [  -n  ${ISET}   ]
    [  -n "${ISET}"  ]
    [  -n  ${ZERO}   ]
    [  -n "${ZERO}"  ]
    [  -n  ${ZLEN}   ]
    [  -n  ${RLEN}   ]
    [  -n "${RLEN}"  ]
    [  -n  ${NULL}   ]
Operator [[ -n ]]
    [[ -n  ${ISET}  ]]
    [[ -n "${ISET}" ]]
    [[ -n  ${ZERO}  ]]
    [[ -n "${ZERO}" ]]
    [[ -n  ${RLEN}  ]]
    [[ -n "${RLEN}" ]]
Script Complete - Exiting.

Consider trying the script with different command line arguments, for example:

./test 12 words
./test /s* /s*
Posted Wednesday, October 7th, 2009 under linux, shell scripting, tips and tricks.

Leave a Reply