380 likes | 511 Views
Shell Control Statements. CS465 - UNIX. Shell arithmetic using expr. The standard Bourne shell does not provide built-in arithmetic operators, so we have to use the expr command. Interactive example: $ num=1 $ expr $num + 1 2 $
E N D
Shell Control Statements CS465 - UNIX
Shell arithmetic using expr • The standard Bourne shell does not provide built-in arithmetic operators, so we have to use the expr command. • Interactive example: $ num=1 $ expr $num + 1 2 $ • To assign the result of an expr command to another shell variable, surround it with backquotes: $ sum=`expr $num + 1` $ echo $sum 2 $
Why expr is needed Unless otherwise indicated, all values are assumed to be STRINGS: $ num=1 $ val=$num+1 $ echo $val 1+1 $
Spaces around operator required Shell arithmetic using expr • expr is needed to translate the variables from strings to numbers and performs the indicated math. The result is converted back to a string. • Example: $ var1=3 $ var2=5 $ sum=`expr $var1 + $var2` $ echo $sum 8 $
expr Operators • Math operators: • +,-,*,/, % • (Must use backslash with *) • Comparison of strings (text): • < ,<=,=,!=,>=,> • (Must use backslash with <, <=, >, >=) • Compounds &(and),|(or) (Must use backslash with both)
Spaces around operator still required Multiplication using expr • Asterisk (*) is usually a wildcard character • Must precede the asterisk with a backslash to use it for multiplication within expr. • Example: $ num=5 $ prod=`expr $num \* 3` $ echo $prod 15 $
Parentheses using expr • expr allows you to group expressions using parentheses, but parentheses are metacharacters used to group commands • So the “(“ and “)” characters also need to be preceded by backslashes. • Example: $ num=2 $ echo `expr 5 \* \( $num + 3 \)` 25 $
Floats are illegal! Integer restriction on expr $ cat test6 #!/bin/sh echo –n "Enter a number: " read num sqr=`expr $num \* $num` echo The square of $num is $sqr $ • test6 • Enter a number: 6 • The square of 6 is 36 • $ • test6 • Enter a number: 8.2 • expr: non-numeric argument • $
Student exercise • Write a script that will read in your age as of Dec 31st (of this year), and then compute and display the year you were born.
Exercise Sample Solution $ cat birthyr #!/bin/sh echo "Enter age on Dec 31st: \c" read age curyr=2009 birthyr=`expr $curyr - $age` echo You were born in $birthyr exit 0 $ Enter age on Dec 31st: 47 You were born in 1962 $
Bourne Shell Control Statements • if – conditional execution of one block of commands or another • while – repeatedly execute block of commands until condition is no longer true • for – iterate over a list of values, executing a block of commands once for every item in the list (not directly analogous to HLL for-loops!) • case – multi-way conditional execution
The test command • Use test command to evaluate logical expressions. • test assigns status 0 if the condition is true or 1 if the condition is false. Variable $? holds the status of the last test. • $ cat check • echo –n "Yes or no: " • read answer • test $answer = yes • echo $? • $ • check • Yes or no: yes • 0 • $ • $ check • Yes or no: no • 1 • $
Note space between condition & brackets! test equivalence Square brackets [ ] are used as a “shortcut” for test command: test condition is equivalent to: [ condition ]
Again, note space betweencondition & brackets! • if test condition OR • then • action • fi if [ condition ] then action fi test within if statements testis used by the if statement, to test conditions:
if [ condition ] then command(s) else command(s) fi Must have spaces between condition and square brackets There are no curly braces. The "true" command block extends from then to else (or fi). The "false" command block extends from else to fi. The else block is optional. "fi“, indicating the end, is "if" spelled backwards. if statement
String Conditional Tests s1 = s2 • true if strings s1 and s2 are identical s1 != s2 • true if strings s1 and s2 are not identical -n s1 • true if length of string s1 is nonzero -z s1 • true if length of string s1 is zero
String Condition Example $ namecmp Joe Joe Same names! $ Task: Compare two names $ cat namecmp #!/bin/sh echo Enter 2 names read name1 name2 if [ "$name1" = "$name2" ] then echo Same names! else echo Different names! fi $ $ namecmp Enter 2 names Pam Joe Different names! $ $ namecmp joe Joe Different names! $
if string details • You don't have to use double quotes around a variable expansion, but doing so will prevent syntax errors when the variable is the null string: • Assume an empty string: string="" • if [ "$string" = foo ] • same as if [ "" = foo ] • if [ $string = foo ] • same as if [ = foo ] • This is a syntax error!
Numeric Conditional Tests n1 -eq n2 • true if integers n1 and n2 are equivalent n1 -lt n2 • true if integer n1 is less than n2 n1 -gt n2 • true if integer n1 is greater than n2 n1 -ge n2 • true if integer n1 is greater than or equal to n2 n1 -le n2 • true if integer n1 is less than or equal to n2
Numeric Example #1 – no else Task: Test to see if any arguments were passed into the script. If there were NOT, display a message. • $ cat argscript • #!/bin/sh • if [ $# -eq 0 ] • then • echo No arguments • fi • exit 0 • $ $ argscript No arguments $ argscript hello $
Numeric Example #2 – with else Task: Test to see if any arguments were passed into the script. Display a message either way. $ cat showargs #!/bin/sh if [ $# -eq 0 ] then echo No arguments else echo $# arguments: $* fi exit 0 $ $ showargs No arguments $ showargs Ford GM 2 arguments: Ford GM $
Numeric Condition Example #3 $ cat calcmales #!/bin/sh echo Enter number of total students: read total echo Enter percent male \(1-100\): read percent if [ $percent -gt 100 ] then echo Percent entered is too big else nummale=`expr $percent \* $total / 100` echo There are $nummale male students fi $
Example #3 Execution $ calcmales Enter number of total students: 88 Enter percent male (1-100): 109 Percent entered is too big $ $ calcmales Enter number of total students: 88 Enter percent male (1-100): 50 There are 44 male students $
Student Exercise • Modify previous script to read month and year of birth year and compute your age at the end of the current month..
Exercise Sample Solution $ cat calcage #!/bin/sh echo -n "Enter birth year: " read byr echo -n "Enter birth month: " read bmon curyr=2009 curmon=5 age=`expr $curyr - $byr` if [ $curmon –lt $bmon ] then age=`expr $age – 1` fi echo You will be $age at this month\’s end exit 0 $ calcage Enter birth year: 1962 Enter birth month: 9 You will be 46 at this month’s end $
Logical Conditional Operators expr1 –a expr2 • AND operator between two logical conditions expr1 –o expr2 • OR operator between two logical conditions ! expr1 • unary NOT operator before one logical condition '(' expr1 -a expr2 ')' -o expr3 • Parentheses can be used for grouping • Must use single quotes or backslash
Logical Condition Example $ cat notify #!/bin/sh if [ `whoami` = "smith123" -o \ `whoami` = "jones456" ] then echo "See the system administrator! " fi exit 0 $ notify $
File Conditional Tests -r filename • true if filename exists and is readable -w filename • true if filename exists and is writable -d filename • true if filename exists and is a directory -s filename • true if filename exists and is nonzero in length NOTE: See test or sh manpage for more file conditions
File Condition Example #1 Test to see if the file myprogs exists and is a directory. If so, move to the myprogs directory and list the files in it. $ cat progdir #!/bin/sh if [ -d myprogs ] then cd myprogs ls fi $ progdir file1.c file2.c $
File Condition Example #2 • Script file mvf moves to the user's home directory and prompts for a subdirectory name to move files to. It then checks to see if the named subdirectory exists. If not, the subdirectory is created. Then the files are moved to the subdirectory.
File Condition Script #2 $ cat mvf #! /bin/sh # Moves parameter filenames to subdirectory cd echo Move files to which subdirectory? read subname if [ ! -d $subname ] then echo Creating subdirectory $subname ... mkdir $subname fi mv $* $subname echo Move complete. exit 0 $
File Condition Script #2 Execution $ ls -F $HOME mbox prog1.c prog3.c notes\ prog2.c $ mvf prog1.c prog2.c Move files to which subdirectory? cprogs Creating subdirectory cprogs ... Move complete. $ ls -F $HOME cprogs\ mbox notes\ prog3.c $ cd cprogs $ ls prog1.c prog2.c $
Student Exercise • Write a script which takes ONE argument, a filename. The script should check if the file exists and is readable. If it DOES, display it. If NOT, issue an error message.
Exercise Sample Solution $ cat display #!/bin/sh file=$1 if [ -r $file ] then cat $file else echo File $1 not readable or nonexistent! fi $ display memo File memo not readable or nonexistent! $
Notice then command appears after “elif” statement. elif syntax (i.e.“else if”) Can use elif to create a nested set of “if-then-else” structures. if [ condition ]then action 1elif [ condition ] then action2else action3fi
elif Example #2 $ cat test8 #!/bin/sh users=`who | wc -l` if [ $users -ge 10 ] then echo "Heavy load" elif [ $users -gt 1 ] then echo "Medium load" else echo "Just me!" fi $ test8 Medium load! $
elif Example # - what type is file? #!/bin/sh if [ -d what ] then echo File is a directory ls elif [ -b what ] then echo File is a block special file elif [ -c what ] then echo File is a character special file elif [ -a what ] then echo File exists - unknown file type else echo File does not exist fi