![]() |
| |||||||
|
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
...or rather, what remains in a quoted string, and what does the shell interpret? You will recall from the previous episode that in the statement: combined="The number is $number, the filename is $filename, it is now $date"the shell peeked inside the quotes to interpret '$' and thus expanded shell variables and parameters. Consider this example script called 'quote': $ cat quote#!/bin/sh variable="Hello" echo "$variable from $0" echo '$variable from $0' echo cost=24.50 echo "Cost = $$cost" echo 'Cost = $$cost' echo "Cost = \$$cost" Executing it produces: $ ./quoteHello from ./quote $variable from $0 Cost = 13233cost Cost = $$cost Cost = $24.50 The first echo behaves as expected. In the second, the use of single quotes instead of double quotes prevents 'sh' (or 'bash') from interpreting the $, and hence from expanding '$variable' and the script name '$0'. Single quotes are often used when a string is to be written to a file, or passed to another command, verbatim. In the second part of the script, the first '$' in: echo "Cost = $$cost"is to be taken literally, but the second is to be interpreted as $cost. Neither single quotes nor double quotes will do what we want. In these situations, use double quotes and escape the dollar that is to be taken literally using '\$'. Notice the odd behaviour of $$ - this expands to be the process id of the shell. See the sidebar for more special parameters. In the following example, backslash is used to escape double quotes. The first attempt will not work because the text 'Hello there' is outside of the double quotes: $ var="He said "Hello there""bash: there: command not found so we escape the inner double quotes with a backslash: $ var="He said \"Hello there\""$ echo $var He said "Hello there" Note that a star (*) within double quotes is NOT expanded. Try: echo *versus: echo "*" |
Tell Me More...
|
|
Special Parameters The shell recognizes $0 as the script name, and $1 onwards as the parameters. In addition, one can take advantage of the following expansions: $* - expands to all the parameters passed to the script (but not the script name). $# - expands to the number of parameters passed to the script $$ - expands to the process id (pid) of the shell For example: $ cat ./sps#!/bin/sh echo $0 $1 $2 $3 echo $* echo $# Executing this: $ ./sps one two three fourGives: ./sps one two threeone two three four 4 Try This... The first line of a shell script may be used to specify which shell is to execute the script. Mostly it will be: #!/bin/shWhat appears after #! is interpreted as the name of the executable that will execute the script. It may be any executable capable of interpreting the script. (In fact it can be any executable at all.) Try with #!/bin/ls. Escaping Generally, in Unix a backslash escapes (instructs to take literally) whatever follows it. |
So far we have used shell variables that are local to a shell and persist only while that shell is running. A shell does not inherit variables from its parent, nor does it return the favour. Once a shell has completed execution, its variables are destroyed. Remember that when a script is executed a new shell is created. When the script completes the new shell terminates, its variables are destroyed, and control is returned to the original shell.
Consider the following example:
$ cat callerFollowing this through:
(1) 'var' is set to "goodbye" in the interactive shell.
(2) The script 'caller' is executed, which does not inherit the value of 'var' from its parent shell, as seen by the line 'var = '.
(3) When the script completes, its particular 'var' (set to "Hello") is no more. But, notice that the instance of 'var' from the interactive shell has not been overwritten and is still set to "goodbye". The two 'var' variables may have the same name, but they are different variables that live in different shell executions.
The following example shows what happens to variables when one script (caller) calls another (callee).
$ cat callerExecute 'caller', which will itself execute 'callee':
$ ./caller var = Hello <- from caller inner var = <- from callee inner var = goodbye <- from callee var = Hello <- from caller
Again, notice that the two 'var' variables are distinct. 'Callee' does not inherit the 'var' belonging to 'caller', nor overwrite it.
The shell command:
$ setdisplays the value of all shell variables currently defined. Setting a variable to "" will not destroy it, but simply set it to empty. Use:
$ unset varto remove it completely.
You will notice that 'set' lists many variables, mostly in uppercase, which are termed environment variables.
An environment variable is a shell variable that persists. It is set in one shell and can be read any another shell, script, or in fact any executable that was started by the original shell. The shell provides a means of setting and deleting environment variables, and is responsible for propagating them to sub-shells and executables. Many environment variables are set by the shell itself, and others by the login scripts executed by the shell (see part 11).
To set your own environment variable use:
$ VAR=hi; export VARBy convention, but not necessity, an environment variable is named in upper case. The only difference compared to a standard shell variable is that it is marked for export to the environment when a script or executable is run. Consider this example:
cat callerExecuting this:
(1)Following this through:
(1) First, in the interactive shell, we set and echo environment variable VAR and get 'hello'.
(2) Next, we execute 'caller', which inherits the value of VAR from its parent shell.
(3) Caller then changes this value to 'hi' and echoes it, and calls 'callee'.
(4) 'callee' inherits VAR, displays it, and gives it a new value 'goodbye'.
(5) But now notice that in returning to 'caller' the value of VAR reverts to its old value of 'hi'.
(6) Similarly, when we return to the original interactive shell, VAR reverts to its original value of 'hello'.
This behaviour can easily be explained. When a new command is executed, it inherits the environment from its parent shell (i.e. it inherits all the environment variables, but not the regular shell variables). It is free to use and change the environment. However, when the process exits, the new environment is not passed back. The new command effectively gets a copy of the environment, not access to the original. (In programming terms, this technique represents 'pass by value' and not 'pass by reference' or 'copy back'.)
For those of you familiar with programming languages, shell and environment variables do not need to be declared before they are used. This saves a little time, but can cause problems in larger scripts. A mis-spelt variable is treated as a new and different variable to the one intended, and with no warning.
Next Page
On page 2 I will continue with control constructs - more on 'if', then 'case', 'for' and 'while' loops.
|
|
Part 9 - Shell Scripting 2 (page 1 of 2) |
|