Unix script 4 - variables part I

Just about every programming language in existence has the conceptof variables - a symbolic name for a chunk of memory to whichwe can assign values, read and manipulate its contents. The bourneshell is no exception, and this section introduces idea. This is taken further in Variables - Part IIwhich looks into variables which are set for us by the environment.
Let's look back at our first Hello World example. This could be doneusing variables (though it's such a simple example that it doesn'treally warrant it!)
Note that there must be no spaces around the "=" sign: 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.
If you think about it, this makes sense - how else could you tell it to run the command VAR with its firstargument being "=" and its second argument being "value"?
Enter the following code into var1.sh:


var.sh
#!/bin/sh
MY_MESSAGE="Hello World"
echo $MY_MESSAGE

This assigns the string "Hello World" to the variableMY_MESSAGE then echoes out the value ofthe variable.
Note that we need the quotes around the string Hello World. Whereaswe could get away with echo Hello World because echowill 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 treatit all as one. Otherwise, the shell will try to execute the command Worldafter 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=123abc

Note though that special characters must be properly escaped to avoidinterpretation by the shell.
This is discussed further in Escape Characters.

We can interactively set variable names using the read command; the following script asks you for your name then greets you personally:


var2.sh
#!/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 missedout the double-quotes in line 3, which meant that the single-quote in theword "you're" was unmatched, causing an error. It is this kind of thingwhich can drive a shell programmer crazy, so watch out for them!


This is using the shell-builtin command read which reads aline from standard input into the variable supplied.
Note that even if you give it your full name and don't use double quotesaround the echo command, it still outputs correctly. Howis this done? With the MY_MESSAGE variable earlier we hadto put double quotes around it to set it.
What happens, is that the read command automatically placesquotes around its input, so that spaces are treated correctly. (You willneed to quote the output, of course - e.g. echo "$MY_MESSAGE").






Scope of Variables

Variables in the bourne shell do not have to be declared, as they do in languages like C. But if you try to read an undeclared variable,the result is the empty string. You get no warnings or errors. This can causesome subtle bugs - if you assign MY_OBFUSCATED_VARIABLE=Hello and then echo $MY_OSFUCATED_VARIABLE, you will get nothing (as the secondOBFUSCATED is mis-spelled).

There is a command called export which has a fundamentaleffect on the scope of variables. In order to really know what's goingon with your variables, you will need to understand something about howthis is used.

Create a small shell script, myvar2.sh:


myvar2.sh
#!/bin/sh
echo "MYVAR is: $MYVAR"
MYVAR="hi there"
echo "MYVAR is: $MYVAR"

Now run the script:

$ ./myvar2.sh
MYVAR is:
MYVAR is: hi there

MYVAR hasn't been set to any value, so it's blank. Then we give it a value, and ithas the expected result.
Now run:

$ MYVAR=hello
$ ./myvar2.sh
MYVAR is:
MYVAR is: hi there

It's still not been set! What's going on?!
When you call myvar2.sh from your interactive shell, a newshell is spawned to run the script. This is partly because of the #!/bin/shline at the start of the script, which we discussed earlier.
We need to 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 there

Now look at line 3 of the script: this is changing the value ofMYVAR. But there is no way that this will be passed backto your interactive shell. Try reading the value of MYVAR:

$ echo $MYVAR
hello
$

Once the shell script exits, its environmentis destroyed. But MYVAR keeps its value of hellowithin your interactive shell.
In order to receive environment changes back from the script, we mustsource the script - this effectively runs the script within ourown interactive shell, instead of spawning another shell to run it.
We can source a script via the "." command:

$ MYVAR=hello
$ echo $MYVAR
hello
$ . ./myvar2.sh
MYVAR is: hello
MYVAR is: hi there
$ echo $MYVAR
hi there

The change has now made it out into our shell again! This is how your.profile or .bash_profile file works, for example.
Note that in this case, we don't need to export MYVAR.
Thanks to sway for pointing out that I'd originally said echo MYVAR above, notecho $MYVAR as it should be.One other thing worth mentioning at this point about variables, is toconsider 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

Think about what result you would expect. For example, if you enter "steve"as your USER_NAME, should the script create steve_file?
Actually, no. This will cause an error unless there is a variable called USER_NAME_file. The shell does not know where the variableends and the rest starts. How can we define this?
The answer is, that we enclose the variable itself in curly brackets:


user.sh
#!/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"

The shell now knows that we are referring to the variable USER_NAMEand that we want it suffixed with _file. This can be thedownfall of many a new shell script programmer, as the source of the problemcan be difficult to track down.

Also note the quotes around "${USER_NAME}_file" - if the user entered "Steve Parker" (note thespace) then without the quotes, the arguments passed to touch would be Steve andParker_file - that is, we'd effectively be saying touch Steve Parker_file, whichis two files to be touched, not one. The quotes avoid this. Thanks to Chris for highlighting this.


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值