How To Test bash expression

Shell Scripting

Bash expression are deemed to be true or false by the test command or one of two nonstandard shell reserved words, [[ and ((. The test command compares strings, integers, and various file attributes; (( tests arithmetic expressions, and [[ … ]] does the same as test with the additional feature of comparing regular bash expression.

test, aka [ ... ]

The test command evaluates many kinds of expressions, from file properties to integers to strings. It is a built-in command, and therefore its arguments are expanded just as for any other command. The alternative version ([) requires a closing bracket at the end.

File Tests

Several operators test the state of a file. A file’s existence can be tested with -e (or the nonstandard -a). The type of file can be checked with -f for a regular file, -d for a directory, and -h or -L for a symbolic link. Other operators test for special types of files and for which permission bits are set.

Here are some examples:

test -f /etc/fstab    ## true if a regular file test -h /etc/rc.local ## true if a symbolic link

[ -x $HOME/bin/hw ]    ## true if you can execute the file

Integer Tests

Comparisons between integers use the -eq, -ne, -gt, -lt, -ge, and -le operators.

The equality of integers is tested with -eq:

$ test 1 -eq 1

$ echo $?

0

$ [ 2 -eq 1 ]

$ echo $?

1

Inequality is tested with -ne:

$ [ 2 -ne 1 ]

$ echo $?

0

The remaining operators test greater than, less than, greater than or equal to, and less than or equal to.

String Tests

Strings are concatenations of zero or more characters and can include any character except NUL (ASCII 0). They can be tested for equality or inequality, for nonempty string or null string, and in bash for alphabetical ordering. The = operator tests for equality, in other words, whether they are identical; != tests for inequality. bash also accepts == for equality, but there is no reason to use this nonstandard operator.

Here are some examples:

test "$a" = "$b" [ "$q" != "$b" ]

The -z and -n operators return successfully if their arguments are empty or nonempty:

$ [ -z "" ]

$ echo $?

0

$ test -n ""

$ echo $?

1

The greater-than and less-than symbols are used in bash to compare the lexical positions of strings and must be escaped to prevent them from being interpreted as redirection operators:

$ str1=abc

$ str2=def

$ test "$str1" \< "$str2"

$ echo $?

0

$ test "$str1" \> "$str2"

$ echo $?

1

The previous tests can be combined in a single call to test with the -a (logical AND) and -o (logical

OR operators:

test -f /path/to/file -a $test -eq 1 test -x bin/file -o $test -gt 1

test is usually used in combination with if or the conditional operators && and ||.

[[ … ]]: Evaluate an Expression

Like test, [[ … ]] evaluates an expression. Unlike test, it is not a built-in command. It is part of the shell grammar and not subject to the same parsing as a built-in command. Parameters are expanded, but word splitting and file name expansion are not performed on words between [[ and ]].

It supports all the same operators as test, with some enhancements and additions. It is, however, nonstandard, so it is better not to use it when test could perform the same function.

Enhancements over Test

When the argument to the right of = or != is unquoted, it is treated as a pattern and duplicates the functionality of the case command.

The feature of [[ … ]] that is not duplicated elsewhere in the shell is the ability to match an extended regular expression using the =~ operator:

$ string=whatever

$ [[ $string =~ h[aeiou] ]]

$ echo $?

0

$ [[ $string =~ h[sdfghjkl] ]]

$ echo $?

1

(( … )): Evaluate an Arithmetic Expression

A nonstandard feature, (( arithmetic expression )) returns false if the arithmetic expression

evaluates to zero and returns true otherwise. The portable equivalent uses test and the POSIX syntax for shell arithmetic:

test $(( $a - 2 )) -ne 0

Lists

A list is a sequence of one or more commands separated by semicolons, ampersands, control operators, or newlines. A list may be used as the condition in a while or until loop or as the body of any loop. The exit code of a list is the exit code of the last command in the list.

Conditional execution

Conditional constructs enable a script to decide whether to execute a block of code or to select which of two or more blocks to execute.

if

The basic if command evaluates a list of one or more commands and executes a list if the execution of

is successful:

if 

then



fi

Usually, the is a single command, very often test or its synonym, [. In Listing 3-1, the -z operand to test checks whether a name was entered.

Read and Check Input

read name

if [ -z "$name" ]

then

echo "No name entered" >&2

exit 1 ## Set a failed return code

fi

Using the else keyword, a different set of commands can be executed if the fails, as shown in Listing 3-2.

Prompt for a Number and Check That It Is No Greater Than Ten

printf "Enter a number no greater than 10: " read number

if [ "$number" -gt 10 ]

then

else fi

printf "%d is too big\n" "$number" >&2 exit 1

printf "You entered %d\n" "$number"

More than one condition can be given, using the elif keyword, so that if the first test fails, the second is tried, as shown in Listing 3-3.

Prompt for a Number and Check That It Is Within a Given Range

printf "Enter a number between 10 and 20 inclusive: " read number

if [ "$number" -lt 10 ]

then

printf "%d is too low\n" "$number" >&2 exit 1

elif [ "$number" -gt 20 ]

then

else fi

printf "%d is too high\n" "$number" >&2 exit 1

printf "You entered %d\n" "$number"

Often more than one test is given in the using && and ||.

Conditional Operators, && and ||

Lists containing the AND and OR conditional operators are evaluated from left to right. A command following the AND operator (&&) is executed if the previous command is successful. The part following the OR operator (||) is executed if the previous command fails.

For example, to check for a directory and cd into it if it exists, use this:

test -d "$directory" && cd "$directory"

To change directory and exit with an error if cd fails, use this:

cd "$HOME/bin" || exit 1

The next command tries to create a directory and cd to it. If either mkdir or cd fails, it exits with an error:

mkdir "$HOME/bin" && cd "$HOME/bin" || exit 1

Conditional operators are often used with if. In this example, the echo command is executed if both tests are successful:

if [ -d "$dir" ] && cd "$dir" then

echo "$PWD" fi

case

A case statement compares a word (usually a variable) against one or more patterns and executes the commands associated with that pattern. The patterns are pathname expansion patterns using wildcards (* and ?) and character lists and ranges ([…]). The syntax is as follows:

case WORD in

PATTERN) COMMANDS ;;

PATTERN) COMMANDS ;; ## optional esac

A common use of case is to determine whether one string is contained in another. It is much faster than using grep, which creates a new process. This short script would normally be implemented as a shell function so that it will be executed without creating a new process, as shown in Listing 3-4.

Does One String Contain Another?

case $1 in

*"$2"*) true ;;

*) false ;;

esac

The commands, true and false, do nothing but succeed or fail, respectively.

Another common task is to check whether a string is a valid number. Again, Listing 3-5 would usually be implemented as a function.

Is This a Valid Integer?

case $1 in

*[!0-9]*) false;;

*) true ;;

esac

Many scripts require one or more arguments on the command line. To check whether there are the correct number, case is often used:

case $# in

3) ;; ## We need 3 args, so do nothing

*) printf "%s\n" "Please provide three names" >&2 exit 1

;;

esac

Looping

When a command or series of commands needs to be repeated, it is put inside a loop. The shell provides three types of loop: while, until, and for. The first two execute until a condition is either true or false;

the third loops through a list of words.

while

The condition for a while loop is a list of one or more commands, and the commands to be executed while the condition remains true are placed between the keywords do and done:

while 

do



done

By incrementing a variable each time the loop is executed, the commands can be run a specific number of times:

n=1

while [ $n -le 10 ]

do

echo "$n"

n=$(( $n + 1 ))

done

The true command can be used to create an infinite loop:

while true ## : can be used in place of true do

read x done

A while loop can be used to read line by line from a file:

while IFS= read -r line do

: do something with "$line"

done < FILENAMEy?

until

Rarely used, until loops as long as the condition fails. It is the opposite of while:

n=1

until [ $n -gt 10 ]

do

echo "$n"

n=$(( $n + 1 ))

done

for

At the top of a for loop, a variable is given a value from a list of words. On each iteration, the next word in the list is assigned:

for var in Canada USA Mexico do

printf "%s\n" "$var" done

bash also has a nonstandard form that is similar to that found in the C programming language. The first expression is evaluated when first encountered. The second is a test. The third is evaluated after each iteration:

for (( n=1; n< =10; ++n ))

do

echo "$n"

done

Since this offers no advantage over standard looping methods, it is not used in this book.

break

A loop can be exited at any point with the break command:

while :

do

read x

[ -z "$x" ] && break

Done

With a numeric argument, break can exit multiple nested loops:

for n in a b c d e do

while true do

if [ $RANDOM -gt 20000 ]

then

printf .

break 2 ## break out of both while and for loops elif [ $RANDOM -lt 10000 ]

then

printf '"'

break ## break out of the while loop

fi

done done

echo

continue

Inside a loop, the continue command immediately starts a new iteration of the loop, bypassing any remaining commands:

for n in {1..9} ## See Brace expansion in Chapter 4 do

x=$RANDOM

[ $x -le 20000 ] && continue echo "n=$n x=$x"

Done

Commands

x    test: Evaluates an expression and returns success or failure

x    if: Executes a set of command if a list of commands is successful and optionally executes a different set if it is not

x    case: Matches a word with one or more patterns and executes the commands associated with the first matching pattern

x    while: Repeatedly executes a set of commands while a list of commands executes successfully

x    until: Repeatedly executes a set of commands until a list of commands executes successfully

x    for: Repeatedly executes a set of commands for each word in a list

x    break: Exits from a loop

x    continue: Starts the next iteration of a loop immediately

In case of any ©Copyright or missing credits issue please check CopyRights page for faster resolutions.

Leave a Reply

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