Introduction to Bash Programming part 2 CISC 3130

Introduction to Bash Programming, part 2 CISC 3130 Spring 2011 Fordham Univ. 1

Shell command line syntax ls –R –l ~ Command name argument Options (arguments) Command name and options separated by space Command ends with newline, ; and & 2

Bash special characters Globbing, filename expansion ls *, rm *, etc. Shell expands filename patterns or templates containing special characters Can be turned off: set –f, shopt Shell special characters *, ? , [, ], |, >, <, >> Quotations: single quote, double quote, back quote 3

Shell startup file Profiles: executed for login shell /etc/profile: system wide default, setting environment for all shell. $HOME/. bash_profile : user-specific bash environment default settings Initialization files: executed for login and interactive shell /etc/bashrc: system wide function and aliases for bash $HOME/. bashrc: user-specific initialization files 4

Shell startup file Non-interactive shell: When you run a shell script, a sub-shell (non-interactive shell) is created to execute the script [zhang@storm ~]$. bash_profile # changes to environment variable not visible to current shell . (dot) command: execute a script in current shell [zhang@storm ~]$. ~/. bash_profile ## to run your. bash_profile without relogin, [zhang@storm ~]$source ~/. bash_profile ## same effect as dot command 5

SHELL Variables Different types of variables Environment variables: HOME, PATH, PS 1, PS 2 … Parameter variables: $1, $*, … User defined variables: student, file, x, . . Recall we set PATH variable in lab 1 … PATH=$PATH: . : ~zhang/bin export PATH # so that subshell see the variable too Example: 6 [zhang@storm ~]$ x=1 [zhang@storm ~]$ export x [zhang@storm ~]$ bash [zhang@storm ~]$ echo $x 1

Shell parameter variables If your script is invoked with parameters, shell sets parameter variables $#: the number of parameters $0: the command/script name $1: the first parameter given to the script $2: the second parameter $*: a list of all parameters, seperated by first char in $IFS $@: a list of all parameters, seperated by space Also called positional parameter 7
![User defined variables Declare variables by using them, e. g. , [zhang@storm ~]$ for User defined variables Declare variables by using them, e. g. , [zhang@storm ~]$ for](http://slidetodoc.com/presentation_image_h2/b57a9f2e94d23f6acd4805edc1755541/image-8.jpg)
User defined variables Declare variables by using them, e. g. , [zhang@storm ~]$ for letter in a b c > do > echo "Letter $letter" > done Letter a Letter b Letter c 8
![SHELL Variables Declare variables by using them, e. g. , [zhang@storm ~]$ x=2 ## SHELL Variables Declare variables by using them, e. g. , [zhang@storm ~]$ x=2 ##](http://slidetodoc.com/presentation_image_h2/b57a9f2e94d23f6acd4805edc1755541/image-9.jpg)
SHELL Variables Declare variables by using them, e. g. , [zhang@storm ~]$ x=2 ## note, no space before or after = (WHY? ) [zhang@storm ~]$ echo $x 2 [zhang@storm ~]$ message=Hello world ## should use quotation ! bash: world: command not found [zhang@storm ~]$ message=″Hello world″ [zhang@storm ~]$ echo $message Hello world [zhang@storm ~]$ t=`date` [zhang@storm ~]$ echo $t Thu Feb 10 23: 18: 48 EST 2011 9
![Read variable value from input [zhang@storm ~]$ read timeofday Morning [zhang@storm ~]$ echo Good Read variable value from input [zhang@storm ~]$ read timeofday Morning [zhang@storm ~]$ echo Good](http://slidetodoc.com/presentation_image_h2/b57a9f2e94d23f6acd4805edc1755541/image-10.jpg)
Read variable value from input [zhang@storm ~]$ read timeofday Morning [zhang@storm ~]$ echo Good $timeofday! Good Morning! [zhang@storm ~]$ read greeting Good morning # don’t need to quote [zhang@storm ~]$ echo $greeting [zhang@storm ~]$ Good morning [zhang@storm ~]$ echo “$greeting” is $greeting. What will be the output ? 10

Even nicer output set command, a shell builtin command display current variables, “set” set shell options, “set –f”, “set –n”. . set position parameters, [zhang@storm ~]$ set Hello world; echo $1, $2 Hello world; Combine command substitution and set command [zhang@storm ~]$ set `who am i` [zhang@storm ~]$ echo Welcome, $1! You logged in from $5. 11 [zhang@storm ~]$ set `date` [zhang@storm ~]$ echo The year is $6 The year is 2011

To generate nicer output Command substitution: substitute output of a command (sequence) into another context Syntax: enclose using backquote, or $() As argument for another command rm `ls *. o` To set a variable time 1=$(date); echo $times 1 To be used in “for” construct for file in `ls *`; do … done 12
![Variable’s default type: string Variables values are stored as strings [zhang@storm ~]$ number=7+5 [zhang@storm Variable’s default type: string Variables values are stored as strings [zhang@storm ~]$ number=7+5 [zhang@storm](http://slidetodoc.com/presentation_image_h2/b57a9f2e94d23f6acd4805edc1755541/image-13.jpg)
Variable’s default type: string Variables values are stored as strings [zhang@storm ~]$ number=7+5 [zhang@storm ~]$ echo $number 7+5 [zhang@storm ~]$ x=2; y=3 [zhang@storm ~]$ z 1=x+y; z 2=$x+$y [zhang@storm ~]$ echo $z 1 $z 2 # What will be the output? Will learn how to perform arithmetic operations in bash ! 13
![Arithmetic Evaluation arithmetic expression, use the following syntax: [zhang@storm ~]$ x=1 [zhang@storm ~]$ x=$[$x+1] Arithmetic Evaluation arithmetic expression, use the following syntax: [zhang@storm ~]$ x=1 [zhang@storm ~]$ x=$[$x+1]](http://slidetodoc.com/presentation_image_h2/b57a9f2e94d23f6acd4805edc1755541/image-14.jpg)
Arithmetic Evaluation arithmetic expression, use the following syntax: [zhang@storm ~]$ x=1 [zhang@storm ~]$ x=$[$x+1] ## x now has value of 2 [zhang@storm ~]$ y=$((2*$x+16)) ## y now has value of 20 Note: spaces around operators optional Complex expressions supported Alternatively, one can use command expr (less efficient) 14 [zhang@storm ~]$ x=`expr $x + 1` # increment x by 1 [zhang@storm ~]$ x=$(expr $x * 2 ) Recall: two diff. syntaxes for command substitution; spaces

Declare variable One can explicitly declare a variable: declare OPTION(s) VARIABLE=value Option -a: variable is an array -f : use function names only -i: variable is to be treated as an integer; arithmetic evaluation is performed when the variable is assigned a value … 15
![Example of numerical variable [zhang@storm ~]$ declare -i x [zhang@storm ~]$ x=10 [zhang@storm ~]$ Example of numerical variable [zhang@storm ~]$ declare -i x [zhang@storm ~]$ x=10 [zhang@storm ~]$](http://slidetodoc.com/presentation_image_h2/b57a9f2e94d23f6acd4805edc1755541/image-16.jpg)
Example of numerical variable [zhang@storm ~]$ declare -i x [zhang@storm ~]$ x=10 [zhang@storm ~]$ x=x+1 [zhang@storm ~]$ echo $x 11 [zhang@storm ~]$ read x 30 [zhang@storm ~]$ x=x*2 [zhang@storm ~]$ echo $x 60 [zhang@storm ~]$ 16

A bash based calculator First, let’s implement addition echo ″calculate x+y″ echo –n ″x=″ ## -n option asks echo not to print newline read x echo –n ″y=″ read y echo ″x+y=″ $(($x + $y)) Will extend it to implement subtraction, multiplication and division Need to read and test operator 17

A bash based calculator to implement subtraction, multiplication and division 18 echo –n ″x=″ read x echo –n “operator(+, -, *, /): ” read op echo –n ″y=″ read y ## if the operator is +: echo $x $op $y = $(($x + $y)) ## if operator is -: echo $x $op $y = $(($x + $y)) … ## How to test condition, and choose different course of actions?

Control Structures Control structures in bash if … then … fi if … then … else … fi if … then …elif … else … fi for … in … done while … done until … done case … in … esac First, conditions (tests) used in if… structures, while, until structures 19

Test: any command/script/function Any command that returns a status of zero when it succeeds and some other status when it fails. [zhang@storm Codes]$ cp cond 1 cond 2 [zhang@storm Codes]$ if diff cond 1 cond 2 >& /dev/null > then > echo "same" > else > echo "not same" > fi same Command diff return 0 if two files are the same … Your script/program/function should return 0 when it exits normally, and return non zero value when it fails 20

Test status of file: file conditionals Unary expressions examining the status of a file Enclosed by [] or [[ ]], or use test command if [ -f /etc/. bashrc ] ## a special command same as test –f /etc/. bashrc then ##. . . fi More testing -d file: true if the file is a directory -e file: true if the file exists 21 -f file: true if the file is a regular file. -s file: true if the file has nonzero size

Test: numerical or string comparison Numerical comparison tests echo -n "Enter your age: " read age if [ $age -lt 18 ] then echo "You need to be 18 or older to apply for account" else echo "Choose your preferred account name" fi 22

Arithmetic Comparison Arithmetic comparison: exp 1 –eq exp 2: true if two expressions are equal exp 1 –ne exp 2: true if two expressions are not equal -lt < , -gt > , -le <= , -ge >= ! exp 1: true if exp 1 if false Example Script: if [ $# -lt 2 ] ## less than 2 command lines arguments then echo “usage: $0 file 1 file 2” exit 1 ## 0 means succeed, otherwise failed fi 23

Conditions: string comparison String comparison string 1 == string 2: strings are equal String 1 != string 2: strings are not equal -n string: string is not null -z string: string is null Exercise #1: Write a script that read from standard input a string, and check if it’s the same as your secret password “secret”; if yes, print out “welcome!”; print out “Go away” if not. 24

Testing in interactive shell first Write a script that read from standard input a string, and check if it’s the same as your secret password “secret”; if yes, print out “welcome!”; print out “Go away” if not. We first test it out using interactive shell: [zhang@storm ~]$ read string Secret [zhang@storm ~]$ if [ $string == "secret" ]; then echo "Welcome"; else echo "Go away"; fi Welcome Important note: the spaces before and after [, ] To put if, then in one line, add ; (command terminator) 25
![[zhang@storm ~]$ cat checkps #!/bin/bash echo -n "Enter your password: " read password if [zhang@storm ~]$ cat checkps #!/bin/bash echo -n "Enter your password: " read password if](http://slidetodoc.com/presentation_image_h2/b57a9f2e94d23f6acd4805edc1755541/image-26.jpg)
[zhang@storm ~]$ cat checkps #!/bin/bash echo -n "Enter your password: " read password if [ $password == "secret" ] then echo "Welcome!" else echo "Go away!" fi [zhang@storm ~]$ checkps Enter your password: secret Welcome! [zhang@storm ~]$ checkps Enter your password: guess Go away! [zhang@storm ~]$ Important note: When spanning multiple lines, do not need the ; 26
![Logic operators: AND if [ $condition 1 ] && [ $condition 2 ] # Logic operators: AND if [ $condition 1 ] && [ $condition 2 ] #](http://slidetodoc.com/presentation_image_h2/b57a9f2e94d23f6acd4805edc1755541/image-27.jpg)
Logic operators: AND if [ $condition 1 ] && [ $condition 2 ] # Same as: if [ $condition 1 -a $condition 2 ] # Returns true if both condition 1 and condition 2 hold true. . . if [[ $condition 1 && $condition 2 ]] # Also works. # Note that && operator not permitted within [. . ] operator: ||, -o and robust ! [[Logic ]] is. OR more versatile 27 Logic NOT operator: !

if control structure Single-line Syntax if TEST-COMMANDS; then CONSEQUENT-COMMANDS; fi 1. TEST-COMMAND is executed 2. if its return status is zero, CONSEQUENT-COMMANDS is executed. Multi-line Syntax if TEST-COMMANDS then CONSEQUENT-COMMANDS fi Recall: command line terminates with NEWLINE, ; , &. 28
![Nested if … then … else statement if [[ "$op" == "+" ]] elif Nested if … then … else statement if [[ "$op" == "+" ]] elif](http://slidetodoc.com/presentation_image_h2/b57a9f2e94d23f6acd4805edc1755541/image-29.jpg)
Nested if … then … else statement if [[ "$op" == "+" ]] elif [[ "$op" == "*" ]] then result=$(($x + $y)) result=$(($x * $y)) echo $x $op $y = $result echo $x * $y = $result elif [[ "$op" == "-" ]] elif [[ "$op" == "/" ]] then result=$(($x - $y)) result=$(($x / $y)) echo $x $op $y = $result else echo "Unknow operator $op" fi 29

30 if… statements can be nested #!/bin/bash # This script will test if we're in a leap year or not. year=`date +%Y` if [ $[$year % 400] -eq 0 ]; then echo "This is a leap year. February has 29 days. " elif [ $[$year % 4] -eq 0 ]; then if [ $[$year % 100] -ne 0 ]; then echo "This is a leap year, February has 29 days. " else echo "This is not a leap year. February has 28 days. " fi else echo "This is not a leap year. February has 28 days. "

Loop structure: while loop Multi-line Syntax: while condition do statements done Single-line Syntax (useful in interactive mode) while condition; do statements; done Note: condition and statements terminates with ; 31
![Loop structure: while loop Example: declare –i i=1 while [ $i -le 10 ]; Loop structure: while loop Example: declare –i i=1 while [ $i -le 10 ];](http://slidetodoc.com/presentation_image_h2/b57a9f2e94d23f6acd4805edc1755541/image-32.jpg)
Loop structure: while loop Example: declare –i i=1 while [ $i -le 10 ]; do echo "loop $i"; i=i+1; done; 32

Exercise: twopower Write a script that print out the following output: 2^0=1 2^1=2 2^2=4 2^3=8 … 2^10=1024 33

Control Structures Control structures in bash if … then … fi if … then … else … fi if … then …elif … else … fi for … in … done while … done until … done case … in … esac 34

Bash Programming: Loop Structure for construct: to loop through a set of values, which can be any set of strings for student in jack, john, alice do echo “Hello, $student” > greeting_$student write $student < greeting_$student done 35

Using for loop Use for loop to print out 2’s power Command seq: print out a sequence of number #!/bin/bash # print out 2’s powers for a in `seq 1 10` do echo 2^$a=$((2**a)) done Note: ** is the exponent operator

Another example … Save student account name in a file, all. txt for student in `cat all. txt` do echo “Hello, $student” > greeting_$student grep $student_rec. txt >>greeting_$student write $student < greeting_$student rm greeting_$student done exit 37 How to avoid using the temporary file, greeting_$student ?

case construct: branching case construct is analogus to switch in C/C++. shorthand for multiple if/then/else statements case "$variable" in "$condition 1" ) command. . . ; ; "$condition 2" ) command. . . ; ; esac 38 • Quoting variables is not mandatory, since word splitting does not take place. • Each test line ends with a ) • Each condition block ends with ; ; • If a condition tests true, then associated commands execute and the case block terminates. • entire case block ends with an esac

Calculator using case block case "$op" in "+" ) result=$(($x + $y)) echo $x $op $y = $result; ; "-" ) result=$(($x - $y)) echo $x $op $y = $result; ; "*" ) result=$(($x * $y)) echo $x * $y = $result; ; "/" ) result=$(($x / $y)) echo $x $op $y = $result; ; *) echo Unknow operator $op; ; esac 39 Demo: fileop script cp ~/zhang/public_html/CISC 3130/Codes/fileop.

Until loop Tests for a condition at the top of a loop, and keeps looping as long as that condition is false (opposite of while loop). until [ condition-is-true ] do command(s). . . done E. g. : 40 $until [ $passwd == "secret" ] ; do echo -n "Try again: "; read passwd; done Try again: guess Try again: password Try again: secret

Summary Variables: environment, user-defined, parameter variable (i. e. , positional parameter) Default type is string Use declare to declare a variable of other type Variable asssignment: counter=1 set command can be used to set positional parameter Arithmetic operations: +, -, *, /, **, %, … x=$[$x+1] ## or x=$(($x+1)) x=x+1 ## if x is numerial type, declare –i x 41

Summary: bash test Any command/function/script that return 0 when succeed, non-zero if fail if ! cp file 1. txt. bak then echo “failed to back up file 1. txt” fi • Test command: use test, or [ ], or [[ ]] • File testing: if [ -d $file ] ## if $file is a directory • String comparison: if [ $input = “secret” ] • Numerical comparison: if [ $i –eq 10 ] • Logic operations: [[ $age –le 50 && $age –gt 18 ]] 42

Summary: control structure They can be nested (just like programming languages) They can a command, so, standard input/output redirection and pipeline can be applied to the whole command For example, we can read from a file: while read line do if [[ "$line" =~ "if" ]] ## matching, regular expression style then echo Found in $line fi done < testleap

Advanced Bash Scripting Topics String operations: Obtain Length Extraction Strip Replace Array Regular expressions Here document Functions

C++ style for loop #!/bin/bash #Declare array with 4 elements ARRAY=( 'Debian Linux' 'Redhat Linux' Ubuntu Linux ) # get number of elements in the array ELEMENTS=${#ARRAY[@]} # echo each element in array # for loop for (( i=0; i<$ELEMENTS; i++)); do echo ${ARRAY[${i}]} done
- Slides: 45