Objective: SOS with "Hell" scripting ;)
This post is a scratch book to collect some tips about shell script programming that have caused me some silly headaches since I started using Linux and Its useful shell scripting features
Contents
Debugging
When you are in trouble maybe this can help and provide you better debugging info than when running your shell script normally
sh -x shellscript.sh
IFS
IFS is a system var that defines what is considered the field separator in a list when being parsed by a loop. If you don't define it properly you won't get the desired results.This
for i in `cat /etc/services`; do echo $i; done
is not the same as this
IFS=$'\n';for i in `cat /etc/services`; do echo $i; done
So for god shake be very careful with the ' marks and the $ ...why this?? i took me enough time to discover this to research why, anyway Ill be graceful if you sent me an email in case you know
String assignment
As a good programmer or good-wannabe programmer you may want your code to be clean an readable, thus you may assign values something like this foo = 7. NOPE NOPE NOPE, your shell is not going to like it, it expects foo=7, this is no spaces in between
Conditionals
If clauses can be used like this:
if [ expression ] then <actions_if_true> else <actions_if_false> fi #or [[ <expression> ]] && <actions_if_true> || <actions_if_false> #or using the "test" clause
It is very important to respect the blank spaces between the brackets
In order to use double conditions, it should be
# expression1 and expression2 must be true if [ expression1 -a expression2 ] if [ expression1 ] && [ expression2 ] # either expression1 or expression2 have to be true if [ expression1 -o expression2 ] if [ expression1 ] || [ expression2 ]
String comparison
After reading the last tip you would use string comparison inside conditional clauses like this:
if [ $foo="something" ] ...
NOOOOOOOOOOOOPE!! Shell scripting does not like it this way, you should separate it or It will understand you are just assigning. This should be correct:
if [ $foo = "something" ] ...
By the way take care with strings that contain blank spaces, in that case your comparison should look like:
if [ "$foo" = "something containing blank spaces" ] ...
Command output assignment
In the same way you assign a value to a variable you can assign the output of a function or external command, to do so you would use the following syntax:
foo=`cat /etc/services`
Bear in mind there shouldn't be any blank space surrounding the = sign
Number comparison
When you are comparing numbers in a conditional clause you must do it in the following way, this is, using -eq, -lt, -gt, etc.
if [ 1 -eq $i ]
Bear in mind there shouldn't be any blank space surrounding the = sign
Function return value
Shell script does not have "return" clause, therefore the first value you "echoed" inside a function is taken as the return value. Wait I didn't explain how to define a function:
function_A(){ sum=`expr $1 + $2` echo "Im the return value:$sum" } param1=1 param2=2 echo `function_A $param1 $param2`
Keep an eye on the following things
- The function declaration does not declare parameter types and therefore parentheses are always with no parameters inside
- The parameters are accesses as $N where "N" is the number of the parameter ($1=param1,$2=param2)
- In the function invocation the parameters are specified next to the function name without parenthesis.
Debugging help
When you have nested loops you want to stop things to see how the script is running, you can achieve this by using a "readline" stop that will be continued after you press the enter key:
... read $foo ...
Floating point calculation
Believe it or not but you cannot use decimal numbers inside shell script, therefore you carry those decimal/floating point numbers contained in string variables and then you operate them with a command called bc. An example can be seen below:
function_A(){ sum=`echo "$1+$2"|bc` echo "Im the return value:$sum" } param1=1.2 param2=2.8 echo `function_A $param1 $param2`
Strictly integer variables
Variables in Shellscript tend to be types-bisexual they can accept strings or numbers. In some conditional clauses we see that the shellscript parser is complaining about the types that should be equal. For this cases you can define an strictly int variable and assign it a number from a string variable that will be casted to integer.
max_hits=10 typeset -i hit=0 hit="4" if [ $max_hits -lt $hit ] ...
Otherwise in the if clause we would see an "unary operation expected" exception.
Bash arrays
wow yeah! Bash shell do handle arrays, its usage is describe in the following examples
#instantiation example array=(11 2 3 4 5 10 8) #or array[0]=0 #length ${#ports[*]} #read form it, $i is a number ${ports[$i]} #write to it, $i is a number ports[$i]=7
Concurrent execution
Commands in a shellscript are executed in sequential order, this is command in line 4 won't be executed before command in line 3 is finished. If we wanted the script not to wait for certain commands or group or commands we use the & symbol.
The sequential execution 4 will appear before the execution 3 because the concurrent lines do not make the script wait for them
No comments:
Post a Comment