Prev (A First Script) | Next (Wildcards) |
VAR=value
works; VAR = value
doesn't work.
In the first case, the shell sees the "=" symbol and treats the command as a variable assignment.
In the second case, the shell assumes that VAR must be the name of a command and tries to execute it.#!/bin/sh MY_MESSAGE="Hello World" echo $MY_MESSAGE
MY_MESSAGE
then echo
es out the value of
the variable.
echo Hello World
because echo
will take any number of parameters, a variable can only hold one value,
so a string with spaces must be quoted to that the shell knows to treat
it all as one. Otherwise, the shell will try to execute the command World
after assigning MY_MESSAGE=Hello
The shell does not care about types of variables; they may store strings,
integers, real numbers - anything you like.
People used to Perl may be quite happy with this; if you've grown up with C, Pascal,
or worse yet Ada, this may seem quite strange.
In truth, these are all stored as strings, but routines which expect a number can treat them as such.
If you assign a string to a variable then try to add 1 to it, you will not get away with it:
$ x="hello" $ y=`expr $x + 1` expr: non-numeric argument $Since the external program
expr
only expects numbers.
But there is no syntactic difference between:
MY_MESSAGE="Hello World" MY_SHORT_MESSAGE=hi MY_NUMBER=1 MY_PI=3.142 MY_OTHER_PI="3.142" MY_MIXED=123abcNote though that special characters must be properly escaped to avoid interpretation by the shell.
We can interactively set variable names using the read
command;
the following script asks you for your name then greets you personally:
#!/bin/sh echo What is your name? read MY_NAME echo "Hello $MY_NAME - hope you're well."Mario Bacinsky kindly pointed out to me that I had originally missed out the double-quotes in line 3, which meant that the single-quote in the word "you're" was unmatched, causing an error. It is this kind of thing which can drive a shell programmer crazy, so watch out for them!
read
which reads a
line from standard input into the variable supplied.
echo
command, it still outputs correctly. How
is this done? With the MY_MESSAGE
variable earlier we had
to put double quotes around it to set it.
read
command automatically places
quotes around its input, so that spaces are treated correctly. (You will
need to quote the output, of course - e.g. echo "$MY_MESSAGE"
).
MY_OBFUSCATED_VARIABLE=Hello
and
then echo $MY_OSFUCATED_VARIABLE
, you will get nothing (as the second
OBFUSCATED is mis-spelled).
There is a command called export
which has a fundamental
effect on the scope of variables. In order to really know what's going
on with your variables, you will need to understand something about how
this is used.
Create a small shell script, myvar2.sh
:
#!/bin/sh echo "MYVAR is: $MYVAR" MYVAR="hi there" echo "MYVAR is: $MYVAR"
$ ./myvar2.sh MYVAR is: MYVAR is: hi thereMYVAR hasn't been set to any value, so it's blank. Then we give it a value, and it has the expected result.
$ MYVAR=hello $ ./myvar2.sh MYVAR is: MYVAR is: hi thereIt's still not been set! What's going on?!
myvar2.sh
from your interactive shell, a new
shell is spawned to run the script. This is partly because of the #!/bin/sh
line at the start of the script, which we discussed earlier.
export
the variable for it to be inherited by another program -
including a shell script. Type:
$ export MYVAR $ ./myvar2.sh MYVAR is: hello MYVAR is: hi thereNow look at line 3 of the script: this is changing the value of
MYVAR
. But there is no way that this will be passed back
to your interactive shell. Try reading the value of MYVAR
:
$ echo $MYVAR hello $Once the shell script exits, its environment is destroyed. But
MYVAR
keeps its value of hello
within your interactive shell.
$ MYVAR=hello $ echo $MYVAR hello $ . ./myvar2.sh MYVAR is: hello MYVAR is: hi there $ echo $MYVAR hi thereThe change has now made it out into our shell again! This is how your
.profile
or .bash_profile
file works, for example.export MYVAR
.
echo MYVAR
above, not
echo $MYVAR
as it should be.
One other thing worth mentioning at this point about variables, is to consider the following shell script:
#!/bin/sh echo "What is your name?" read USER_NAME echo "Hello $USER_NAME" echo "I will create you a file called $USER_NAME_file" touch $USER_NAME_file
steve_file
?USER_NAME_file
. The shell does not know where the variable
ends and the rest starts.
How can we define this?
#!/bin/sh echo "What is your name?" read USER_NAME echo "Hello $USER_NAME" echo "I will create you a file called ${USER_NAME}_file" touch "${USER_NAME}_file"
USER_NAME
and that we want it suffixed with _file
. This can be the
downfall of many a new shell script programmer, as the source of the problem
can be difficult to track down.
Also note the quotes around "${USER_NAME}_file"
- if the user entered "Steve Parker" (note the
space) then without the quotes, the arguments passed to touch
would be Steve
and
Parker_file
- that is, we'd effectively be saying touch Steve Parker_file
, which
is two files to be touch
ed, not one. The quotes avoid this. Thanks to Chris for highlighting this.
Prev (A First Script) | Next (Wildcards) |