Chapter 7. Tests. Comtrol DeviceMaster Software Development Kit
જાહેરાત
જાહેરાત
Chapter 7. Tests
Every reasonably complete programming language can test for a condition, then act according to the result of
7.1. Test Constructs
•
by UNIX convention), and if so, executes one or more commands.
•
and a builtin for efficiency reasons. This command considers its arguments as comparison expressions
or file tests and returns an exit status corresponding to the result of the comparison (0 for true, 1 for false).
•
With version 2.02, Bash introduced the [[ ... ]] extended test command, which performs comparisons
in a manner more familiar to programmers from other languages. Note that [[ is a keyword, not a
command.
•
Bash sees
[[ $a -lt $b ]]
as a single element, which returns an exit status.
they evaluate expand to a non-zero value. These arithmetic-expansion constructs may therefore be
used to perform arithmetic comparisons.
(( 0 && 1 )) # Logical AND echo $? # 1 ***
# And so ...
let "num = (( 0 && 1 ))" echo $num # 0
# But ...
let "num = (( 0 && 1 ))" echo $? # 1 ***
(( 200 || 11 )) # Logical OR echo $? # 0 ***
# ...
let "num = (( 200 || 11 ))" echo $num # 1 let "num = (( 200 || 11 ))" echo $? # 0 ***
(( 200 | 11 )) # Bitwise OR echo $? # 0 ***
# ...
let "num = (( 200 | 11 ))" echo $num # 203 let "num = (( 200 | 11 ))" echo $? # 0 ***
# The "let" construct returns the same exit status
#+ as the double-parentheses arithmetic expansion.
Chapter 7. Tests 54
Advanced Bash-Scripting Guide
Again, note that the exit status of an arithmetic expression is not an error value.
var=-2 && (( var+=2 )) echo $? # 1 var=-2 && (( var+=2 )) && echo $var
# Will not echo $var!
•
An if can test any command, not just conditions enclosed within brackets.
if cmp a b &> /dev/null # Suppress output.
then echo "Files a and b are identical." else echo "Files a and b differ." fi
# The very useful "if-grep" construct:
# ----------------------------------- if grep -q Bash file
then echo "File contains at least one occurrence of Bash." fi word=Linux letter_sequence=inu if echo "$word" | grep -q "$letter_sequence"
# The "-q" option to grep suppresses output.
then
echo "$letter_sequence found in $word" else
echo "$letter_sequence not found in $word" fi if COMMAND_WHOSE_EXIT_STATUS_IS_0_UNLESS_ERROR_OCCURRED
then echo "Command succeeded."
else echo "Command failed." fi
•
These last two examples courtesy of Stéphane Chazelas.
Example 7-1. What is truth?
#!/bin/bash
# Tip:
# If you're unsure how a certain condition might evaluate,
#+ test it in an if-test.
echo echo "Testing \"0\"" if [ 0 ] # zero then
echo "0 is true." else # Or else ...
echo "0 is false." fi # 0 is true.
echo
Chapter 7. Tests 55
Advanced Bash-Scripting Guide echo "Testing \"1\"" if [ 1 ] # one then
echo "1 is true." else
echo "1 is false." fi # 1 is true.
echo echo "Testing \"-1\"" if [ -1 ] # minus one then
echo "-1 is true." else
echo "-1 is false." fi # -1 is true.
echo echo "Testing \"NULL\"" if [ ] # NULL (empty condition) then
echo "NULL is true." else
echo "NULL is false." fi # NULL is false.
echo echo "Testing \"xyz\"" if [ xyz ] # string then
echo "Random string is true." else
echo "Random string is false." fi # Random string is true.
echo echo "Testing \"\$xyz\"" if [ $xyz ] # Tests if $xyz is null, but...
# it's only an uninitialized variable.
then
echo "Uninitialized variable is true." else
echo "Uninitialized variable is false." fi # Uninitialized variable is false.
echo echo "Testing \"-n \$xyz\"" if [ -n "$xyz" ] # More pedantically correct.
then
echo "Uninitialized variable is true." else
echo "Uninitialized variable is false." fi # Uninitialized variable is false.
echo
Chapter 7. Tests 56
Advanced Bash-Scripting Guide xyz= # Initialized, but set to null value.
echo "Testing \"-n \$xyz\"" if [ -n "$xyz" ] then
echo "Null variable is true." else
echo "Null variable is false." fi # Null variable is false.
echo
# When is "false" true?
echo "Testing \"false\"" if [ "false" ] # It seems that "false" is just a string ...
then
echo "\"false\" is true." #+ and it tests true.
else
echo "\"false\" is false." fi # "false" is true.
echo echo "Testing \"\$false\"" # Again, uninitialized variable.
if [ "$false" ] then
echo "\"\$false\" is true." else
echo "\"\$false\" is false." fi # "$false" is false.
# Now, we get the expected result.
# What would happen if we tested the uninitialized variable "$true"?
echo exit 0
Exercise.
Explain the behavior of Example 7-1, above.
if [ condition-true ] then
command 1
command 2
...
else # Or else ...
# Adds default code block executing if original condition tests false.
command 3
command 4
...
fi
When if and then are on same line in a condition test, a semicolon must terminate the if statement. Both if
and then are keywords. Keywords (or commands) begin statements, and before a new statement on the
same line begins, the old one must terminate.
Chapter 7. Tests 57
if [ -x "$filename" ]; then
Advanced Bash-Scripting Guide
Else if and elif
elif
elif
is a contraction for else if. The effect is to nest an inner if/then construct within an outer one.
if [ condition1 ] then
command1
command2
command3 elif [ condition2 ]
# Same as else if then
command4
command5 else
default-command fi
The
if test condition-true
construct is the exact equivalent of
if [ condition-true ]
. As it happens, the left bracket, [ , is a token [33] which invokes the test command. The closing right bracket, ] , in an if/test should not therefore be strictly necessary, however newer versions of Bash require it.
The test command is a Bash builtin which tests file types and compares strings. Therefore, in a Bash
script, test does not call the external
/usr/bin/test
binary, which is part of the sh-utils package.
Likewise, [ does not call
/usr/bin/[
, which is linked to
/usr/bin/test
.
bash$
type test
test is a shell builtin bash$
type '['
[ is a shell builtin bash$
type '[['
[[ is a shell keyword bash$
type ']]'
]] is a shell keyword bash$
type ']'
bash: type: ]: not found
If, for some reason, you wish to use
/usr/bin/test
in a Bash script, then specify it by full pathname.
Example 7-2. Equivalence of test,
/usr/bin/test
, [ ], and
/usr/bin/[
#!/bin/bash echo if test -z "$1" then
echo "No command-line arguments." else
echo "First command-line argument is $1."
Chapter 7. Tests 58
Advanced Bash-Scripting Guide fi echo if /usr/bin/test -z "$1" # Equivalent to "test" builtin.
# ^^^^^^^^^^^^^ # Specifying full pathname.
then
echo "No command-line arguments." else
echo "First command-line argument is $1." fi echo if [ -z "$1" ] # Functionally identical to above code blocks.
# if [ -z "$1" should work, but...
#+ Bash responds to a missing close-bracket with an error message.
then
echo "No command-line arguments." else
echo "First command-line argument is $1." fi echo if /usr/bin/[ -z "$1" ] # Again, functionally identical to above.
# if /usr/bin/[ -z "$1" # Works, but gives an error message.
# # Note:
# This has been fixed in Bash, version 3.x.
then
echo "No command-line arguments." else
echo "First command-line argument is $1." fi echo exit 0
The [[ ]] construct is the more versatile Bash version of [ ]. This is the extended test command, adopted from
ksh88.
* * *
No filename expansion or word splitting takes place between [[ and ]], but there is parameter expansion and command substitution.
file=/etc/passwd if [[ -e $file ]] then
echo "Password file exists." fi
Using the [[ ... ]] test construct, rather than [ ... ] can prevent many logic errors in scripts. For example, the
&&, ||, <, and > operators work within a [[ ]] test, despite giving an error within a [ ] construct.
Chapter 7. Tests 59
Advanced Bash-Scripting Guide
Arithmetic evaluation of octal / hexadecimal constants takes place automatically within a [[ ... ]] construct.
# [[ Octal and hexadecimal evaluation ]]
# Thank you, Moritz Gronbach, for pointing this out.
decimal=15 octal=017 # = 15 (decimal) hex=0x0f # = 15 (decimal) if [ "$decimal" -eq "$octal" ] then
echo "$decimal equals $octal" else
echo "$decimal is not equal to $octal" # 15 is not equal to 017 fi # Doesn't evaluate within [ single brackets ]!
if [[ "$decimal" -eq "$octal" ]] then
echo "$decimal equals $octal" # 15 equals 017 else
echo "$decimal is not equal to $octal" fi # Evaluates within [[ double brackets ]]!
if [[ "$decimal" -eq "$hex" ]] then
echo "$decimal equals $hex" # 15 equals 0x0f else
echo "$decimal is not equal to $hex" fi # [[ $hexadecimal ]] also evaluates!
Following an if, neither the test command nor the test brackets ( [ ] or [[ ]] ) are strictly necessary.
dir=/home/bozo if cd "$dir" 2>/dev/null; then # "2>/dev/null" hides error message.
echo "Now in $dir." else
echo "Can't change to $dir." fi
The "if COMMAND" construct returns the exit status of COMMAND.
Similarly, a condition within test brackets may stand alone without an if, when used in combination with
var1=20 var2=22
[ "$var1" -ne "$var2" ] && echo "$var1 is not equal to $var2" home=/home/bozo
[ -d "$home" ] || echo "$home directory does not exist."
marked contrast to using the test and [ ] constructs previously discussed.
Chapter 7. Tests 60
Advanced Bash-Scripting Guide
Example 7-3. Arithmetic Tests using (( ))
#!/bin/bash
# arith-tests.sh
# Arithmetic tests.
# The (( ... )) construct evaluates and tests numerical expressions.
# Exit status opposite from [ ... ] construct!
(( 0 )) echo "Exit status of \"(( 0 ))\" is $?." # 1
(( 1 )) echo "Exit status of \"(( 1 ))\" is $?." # 0
(( 5 > 4 )) # true echo "Exit status of \"(( 5 > 4 ))\" is $?." # 0
(( 5 > 9 )) # false echo "Exit status of \"(( 5 > 9 ))\" is $?." # 1
(( 5 == 5 )) # true echo "Exit status of \"(( 5 == 5 ))\" is $?." # 0
# (( 5 = 5 )) gives an error message.
(( 5 - 5 )) # 0 echo "Exit status of \"(( 5 - 5 ))\" is $?." # 1
(( 5 / 4 )) # Division o.k.
echo "Exit status of \"(( 5 / 4 ))\" is $?." # 0
(( 1 / 2 )) # Division result < 1.
echo "Exit status of \"(( 1 / 2 ))\" is $?." # Rounded off to 0.
# 1
(( 1 / 0 )) 2>/dev/null # Illegal division by 0.
# ^^^^^^^^^^^ echo "Exit status of \"(( 1 / 0 ))\" is $?." # 1
# What effect does the "2>/dev/null" have?
# What would happen if it were removed?
# Try removing it, then rerunning the script.
# ======================================= #
# (( ... )) also useful in an if-then test.
var1=5 var2=4 if (( var1 > var2 )) then #^ ^ Note: Not $var1, $var2. Why?
echo "$var1 is greater than $var2" fi # 5 is greater than 4 exit 0
Chapter 7. Tests 61
ડાઉનલોડ કરો
જાહેરાત