Pitfalls of shell scripting. Part1
In this post ( and in the next few posts) I'll try to cover some pitfalls where beginners to shell scripting might find themselves wasting hours looking through the code to find the error.
- No space can occur between the variable name, the equal to sign, and the value.
eg, var1=10 (correct)
var1 = 10 (incorrect)
- '>' operator writes the output to the file name mentioned.
eg., `date` > date.txt
- '>>' appends to the file. Normal '>' overwrites the previous contents.
eg., `date` >> date.txt
- '<' reads from a file mentioned
eg., sort < data
- '<<' is a powerful operator that allows inline input redirection. Instead of specifying a file to read from, with this operator one can specify the inputs in the code itself. The format is that after the << symbol, one can place a marker and continue giving data, ending it with the same marker.
eg., sort << datalist
The last datalist signifies that our data has ended with this marker.
- Legacy style is to use the expr command to evaluate mathematical expressions.
eg., var3=`expr $var1 + $var2`
- Note that we need to use the backtick operator(`) for the shell to identify as a command, since the expr is a command and its output is assigned to the variable var3. But it becomes tedious and too much typing as the expressions get big and ugly.
- So the [ ] can be used to avoid all of this. The same thing can be easily written as
var3=$[$var1 + $var2]
- The part inside the braces can be as complex as needed with "()" used to mark off sub-expressions and so on.
- The problem with bash shell is that it only supports integer arithmetic. Therefore
var1=$[100 / 45] will store 2 as the result.
To overcome this we use the inbuilt bc(bash calculator) tool as it can handle all types of operators.
var1=`echo " 100 / 5" | bc`
- This is a rather convoluted way of giving the inputs to bc but the first way that one can think of.
- bc is a tool that needs inputs, so we echo all of our required expression and pipe it to the bc command.
- We need to include the whole line in the backtick(`) for the shell to interpret it as a command.
- The cool part is that bc can handle variables as well and supports all complex mathematical operations required in real-life applications.
Instead of doing all this, there is also a simple way of doing this. And welcome "<<" operator discussed above.
var3=`bc << end_of_data
a = ( $var1 + $var2 )
b = (a*2)
echo the output is $var3
Note a few points in this example.
- bc can handle variables declared in the main code block
- there is no limitation for assigning values to variables
- there is no limitation in values placed inside the brackets. (Something you'll see later on, exists in the normal bash shell scripts)
UNIX provides a special variable "$?" denoting the exit status from the last command run. But one must use it immediately after the command for which the exit status is to be inspected.
$ echo hello
(Gives the status of echo)
$ touch file1
$ ls file1
(Gives the status of ls, not touch.)
Generally in the UNIX world, some special codes have universal meaning across all commands.
|0||Successful completion of the command|
|1||General unknown error|
|2||Misuse of shell command|
|126||The command can't execute|
|127||Command not found|
|128||Invalid exit argument|
|130||Command terminated with Ctrl-C|
|255||Exit status out of range|
One should use this in designing a script. And it is also handy to determine how a command exited and resume/cancel further operation based on the value.