eval reads arguments as input to the shell (the resulting commands are executed). This allows using the value of a variable as a variable.
paul@deb503:~/test42$ answer=42 paul@deb503:~/test42$ word=answer paul@deb503:~/test42$ eval x=\$$word ; echo $x 42
Both in bash and Korn the arguments can be quoted.
kahlan@solexp11$ answer=42 kahlan@solexp11$ word=answer kahlan@solexp11$ eval "y=\$$word" ; echo $y 42
Sometimes the eval is needed to have correct parsing of arguments. Consider this example where the date command receives one parameter 1 week ago.
paul@debian6~$ date --date="1 week ago" Thu Mar 8 21:36:25 CET 2012
When we set this command in a variable, then executing that variable fails unless we use eval.
paul@debian6~$ lastweek='date --date="1 week ago"' paul@debian6~$ $lastweek date: extra operand `ago"' Try `date --help' for more information. paul@debian6~$ eval $lastweek Thu Mar 8 21:36:39 CET 2012
The (( )) allows for evaluation of numerical expressions.
paul@deb503:~/test42$ (( 42 > 33 )) && echo true || echo false true paul@deb503:~/test42$ (( 42 > 1201 )) && echo true || echo false false paul@deb503:~/test42$ var42=42 paul@deb503:~/test42$ (( 42 == var42 )) && echo true || echo false true paul@deb503:~/test42$ (( 42 == $var42 )) && echo true || echo false true paul@deb503:~/test42$ var42=33 paul@deb503:~/test42$ (( 42 == var42 )) && echo true || echo false false
The let built-in shell function instructs the shell to perform an evaluation of arithmetic expressions. It will return 0 unless the last arithmetic expression evaluates to 0.
[paul@RHEL4b ~]$ let x="3 + 4" ; echo $x 7 [paul@RHEL4b ~]$ let x="10 + 100/10" ; echo $x 20 [paul@RHEL4b ~]$ let x="10-2+100/10" ; echo $x 18 [paul@RHEL4b ~]$ let x="10*2+100/10" ; echo $x 30
The shell can also convert between different bases.
[paul@RHEL4b ~]$ let x="0xFF" ; echo $x 255 [paul@RHEL4b ~]$ let x="0xC0" ; echo $x 192 [paul@RHEL4b ~]$ let x="0xA8" ; echo $x 168 [paul@RHEL4b ~]$ let x="8#70" ; echo $x 56 [paul@RHEL4b ~]$ let x="8#77" ; echo $x 63 [paul@RHEL4b ~]$ let x="16#c0" ; echo $x 192
There is a difference between assigning a variable directly, or using let to evaluate the arithmetic expressions (even if it is just assigning a value).
kahlan@solexp11$ dec=15 ; oct=017 ; hex=0x0f kahlan@solexp11$ echo $dec $oct $hex 15 017 0x0f kahlan@solexp11$ let dec=15 ; let oct=017 ; let hex=0x0f kahlan@solexp11$ echo $dec $oct $hex 15 15 15
You can sometimes simplify nested if statements with a case construct.
[paul@RHEL4b ~]$ ./help What animal did you see ? lion You better start running fast! [paul@RHEL4b ~]$ ./help What animal did you see ? dog Don't worry, give it a cookie. [paul@RHEL4b ~]$ cat help #!/bin/bash # # Wild Animals Helpdesk Advice # echo -n "What animal did you see ? " read animal case $animal in "lion" | "tiger") echo "You better start running fast!" ;; "cat") echo "Let that mouse go..." ;; "dog") echo "Don't worry, give it a cookie." ;; "chicken" | "goose" | "duck" ) echo "Eggs for breakfast!" ;; "liger") echo "Approach and say 'Ah you big fluffy kitty...'." ;; "babelfish") echo "Did it fall out your ear ?" ;; *) echo "You discovered an unknown animal, name it!" ;; esac [paul@RHEL4b ~]$
Shell functions can be used to group commands in a logical way.
kahlan@solexp11$ cat funcs.ksh #!/bin/ksh function greetings { echo Hello World! echo and hello to $USER to! } echo We will now call a function greetings echo The end
This is sample output from this script with a function.
kahlan@solexp11$ ./funcs.ksh We will now call a function Hello World! and hello to kahlan to! The end
A shell function can also receive parameters.
kahlan@solexp11$ cat addfunc.ksh #!/bin/ksh function plus { let result="$1 + $2" echo $1 + $2 = $result } plus 3 10 plus 20 13 plus 20 22
This script produces the following output.
kahlan@solexp11$ ./addfunc.ksh 3 + 10 = 13 20 + 13 = 33 20 + 22 = 42
1. Write a script that asks for two numbers, and outputs the sum and product (as shown here).
Enter a number: 5 Enter another number: 2 Sum: 5 + 2 = 7 Product: 5 x 2 = 10
2. Improve the previous script to test that the numbers are between 1 and 100, exit with an error if necessary.
3. Improve the previous script to congratulate the user if the sum equals the product.
4. Write a script with a case insensitive case statement, using the shopt nocasematch option. The nocasematch option is reset to the value it had before the scripts started.
5. If time permits (or if you are waiting for other students to finish this practice), take a look at Linux system scripts in /etc/init.d and /etc/rc.d and try to understand them. Where does execution of a script start in /etc/init.d/samba ? There are also some hidden scripts in ~, we will discuss them later.
1. Write a script that asks for two numbers, and outputs the sum and product (as shown here).
Enter a number: 5 Enter another number: 2 Sum: 5 + 2 = 7 Product: 5 x 2 = 10
#!/bin/bash echo -n "Enter a number : " read n1 echo -n "Enter another number : " read n2 let sum="$n1+$n2" let pro="$n1*$n2" echo -e "Sum\t: $n1 + $n2 = $sum" echo -e "Product\t: $n1 * $n2 = $pro"
2. Improve the previous script to test that the numbers are between 1 and 100, exit with an error if necessary.
echo -n "Enter a number between 1 and 100 : " read n1 if [ $n1 -lt 1 -o $n1 -gt 100 ] then echo Wrong number... exit 1 fi
3. Improve the previous script to congratulate the user if the sum equals the product.
if [ $sum -eq $pro ] then echo Congratulations $sum == $pro fi
4. Write a script with a case insensitive case statement, using the shopt nocasematch option. The nocasematch option is reset to the value it had before the scripts started.
#!/bin/bash # # Wild Animals Case Insensitive Helpdesk Advice # if shopt -q nocasematch; then nocase=yes; else nocase=no; shopt -s nocasematch; fi echo -n "What animal did you see ? " read animal case $animal in "lion" | "tiger") echo "You better start running fast!" ;; "cat") echo "Let that mouse go..." ;; "dog") echo "Don't worry, give it a cookie." ;; "chicken" | "goose" | "duck" ) echo "Eggs for breakfast!" ;; "liger") echo "Approach and say 'Ah you big fluffy kitty.'" ;; "babelfish") echo "Did it fall out your ear ?" ;; *) echo "You discovered an unknown animal, name it!" ;; esac if [ nocase = yes ] ; then shopt -s nocasematch; else shopt -u nocasematch; fi
5. If time permits (or if you are waiting for other students to finish this practice), take a look at Linux system scripts in /etc/init.d and /etc/rc.d and try to understand them. Where does execution of a script start in /etc/init.d/samba ? There are also some hidden scripts in ~, we will discuss them later.