上篇我们学习了
shell
脚本编程中常用的一些工具,从本篇开始,我们可以尝试编写自己的脚本了。我们依次来讨论以下几个主题:
创建脚本文件
变量
内部整数算术运算
一、创建脚本文件
创建并执行
shell
程序可以直接从终端上键入,如:
$who | wc �Cl
$
或者,也可以先把程序键入一个文件,然后由
shell
来执行这个文件。所要做的事情只有以下几步:
1
、
创建文件
2
、
将程序内容依次键入文件中
3
、
赋予该文件可以被执行的权限
下面演示创建一个
shell
脚本的完整过程
,
脚本的名字叫做
nu
,用于统计系统已登陆用户数。
$vi nu
who | wc �Cl
退出
vi
并保存。
$chmod +x nu
shell
脚本
nu
就创建好了,接下来的任务就是,执行这个脚本。
$./nu
4
$
结果表明,目前有
4
个用户登陆到系统上。
再写一个看起来稍微复杂一点点的脚本
stats
。这次我们打算完成的任务是,输出当前时间、已登陆用户数、当前工作目录。
$cat stats
date
who | wc �Cl
pwd
$chmod +x stats
$./stats
Mon Sep 28 14:04:47 EDT 2009
4
/root/testdir
$
从上面两个脚本,我们可以得到几个结论:只要把命令一条接一条写进脚本,执行时
shell
就按照顺序挨个执行他们,并输出结果;执行命令的时候只要输入脚本带路径的文件名就可以了(
./stats
是一个相对路径)。
注释
如果没有注释,那么
shell
脚本是不完整的,尽管注释对脚本的执行没有影响。维护一个没有任何注释的脚本,是件很痛苦的事。哪怕脚本是维护者自己写的,一段时间以后,也不能保证能完全理解以前写的脚本。
每当
shell
在看到特殊字符
#
后,就会将其后直到行尾的内容视为注释,直接将他们忽略。如果某行以
#
开头,那么
shell
将整行视为注释内容。下面有一些例子:
$cat stats
# Here is a entire commentary line
Date
who | wc �Cl # count the number of users
pwd
# End of script
$
额外的空行几乎不占用什么程序空间,然而可以大大增加程序的可读性,
shell
只是将他们忽略掉。
二、变量
与所有的变成语言一样,
shell
也允许把值存在变量中。
Shell
变量名以字母或下划线字
符开始,后面跟
0
或若干个字母、数字或下划线字符。把值存入变量(俗称赋值)的格式为:
variable=value
例如,要把数值
1
赋值给
shell
变量
count
,只要写
count=1
要把值
/home/steve/bin
赋给
shell
变量
my_bin
,只要写
my_bin=/home/steve/bin
这里有几个关键点:
1
、等号的任何一边不能加空格;
2
、
Shell
没有任何数据类型的概念,
shell
默认将所有赋给变量的值当作字符处理。此外,
shell
可以根据上下文判断是字符还是数字。
显示变量的值
可以用
echo
命令显示变量的值:
$echo $count
1
$echo $my_bin
/home/steve/bin
$
也可以一次显示多个变量:
$echo $count $my_bin
1 /home/steve/bin
$
键入
echo $count
时,
shell
把
$count
替换为
count
所存入的值,然后执行
echo
命令;键入
echo $count $my_bin
时,
sehll
先替换
$count
和
$my_bin
的值,然后执行
echo
命令。
变量值可以用于命令行的任何地方,如:
$ls $my_bin
mon
nu
$
就是命令也能存在变量中:
$command=wc
$option=-l
$file=names
$$command $option $file
4 names
$
因为
sehll
在确定要执行的程序名及其参数之前进行替换,扫描命令行
$command $option $file
并转换成
wc �Cl names
然后再执行
wc
,并传递两个参数
-l
和
names
。
空值
$echo :$nosuch:
: :
$
可以看到,
shell
没有把
$nosuch
替换成任何值,因为我们并没有给变量
nosuch
赋过值。如果一个变量没有值,我们就说它含有空值,这是变量还没有赋值时的默认状态。当
shell
进行变量替换时,任何空值都被完全从命令行中被清除,不留一点痕迹。
文件名替换和变量
如果键入
x=*
执行命令
echo $x
会出现什么结果呢?我们来试试吧:
$ls
1.bak 2.bak 3.bak urfile
$x=*
$echo $x
1.bak 2.bak 3.bak urfile
$
替换的顺序是这样的:
x=*
将符号
*
存入变量
x
中,这一步并不将文件名清单替换出来
echo $x
将
$x
替换成变量
x
的值,也就是
*
,得到
echo *
echo *
被
shell
看到了
*
,所以先把
*
替换为当前目录文件名列表,再执行
echo
。
${variable}
结构
当我们键入
echo $count1
时,
shell
会认为我们要显示变量
count1
的值,还是显示变量
count
的值后面跟
1
呢?答案是显示变量
count1
的值。那么如果我们想要显示
count
的值后面跟
1
,应该怎么做呢?
${}
结构可以帮我们这个忙。看下面的例子:
$count=1
$count1=a
$echo $count1
a
$echo ${count}1
11
$
事实上,
$count
也可以写成
${count}
,只不过这时的
{}
不是必须的。一般情况,当你引用某个变量时,其后还紧跟其他字符,这时应该用
{}
把变量保护起来。
三、内部整数算术运算
Shell
有自己的执行算术运算的机制,称为算术扩展。算术扩展的格式是:
$((expression))
其中
expression
是由变量和运算符构成的算术表达式。下面的例子中,变量
a
开始是没有值的:
$echo $a
$echo $((a=a+1))
1
$echo $a
1
$
表达式还可以用括号来改变优先级,就像小学数学中学的那样:
echo $((i=(i+10)*j))
$a=$((a * 5))
$echo $a
5
$
有两点是需要我们注意的:
1
、
expression
中的变量替换不需要再用
$
引用了,因为
(())
外面已经有
$
;
2
、
expression
中的空格是任选的,但是赋值放到小括号外的话,就不能有空格了。
expression
中还可以使用不等式:
result=$(( i >= 0 && i <= 100))
如果表达式的值为真,就给
result
赋
1
,否则给
result
赋
0
。
$i=$(( 100 * 200 / 10 ))
$j=$(( i < 1000 ))
$echo $i $j
2000 0
$
本篇就介绍到这里了,关于引用、命令替换的内容将在下一篇中介绍。
本文出自 51CTO.COM技术博客