资源描述
《计算机软件基础》多媒体教程
第四讲
第一章 操作系统及Unix Shell
1.6.2 shell程序
※ 什么是shell程序?
由shell命令、shell控制结构和注释、UNIX实用程序以及用户命令(由某种程序编译形成的可执行文件)组成的命令文件称为shell程序,也可称为shell script编程。
例如,my_shell是一个shell程序,文件内容为:
#! /bin/sh 表示本程序采用B shell语法解释(使用B shell解释器)
if test -f $1.c if...then...else...fi是shell的if控制结构
then
# compile 由#引起注释行
cc -o $1 $1.c cc是UNIX的C语言编译命令
$1 $1是shell程序的输入变量,这里作为用户命令使用
else
echo $1 not found echo是shell命令
fi
※ shell程序的执行方式
shell程序的执行方式有两种
(1) 先令需要执行的shell文件成为可执行,即增加可执行模式,然后执行。
例如,采用以下形式:
$ chmod +x shell文件
$ shell文件
例如:
$ chmod +x my_shell
$ my_shell my_cat
从shell程序my_shell的内部来看,输入变量$1的值为my_cat,$1.c 的值为my_cat.c。
(2) 调用shell解释器执行shell文件。
形式为:
$ sh shell文件
例如:
$ sh my_shell my_cat
※ shell程序的特殊变量
⊙ shell命令的一般形式
$ command [option ...] [variable ...]
command 命令名
option 可选项参数,以“-”开头
variable 命令变量
option和variable统称为命令行参数(parameter) 或者命令行变量。参数的数量根据不同的命令而定,这些参数都可以传递到shell程序内部。
⊙ 特殊变量
从shell程序的内部看命令行参数,用下列特殊变量表示:
$0 命令名本身
$1 命令行的第一个参数
$2 命令行的第二个参数
$3 命令行的第三个参数
$# 命令行参数的个数
$* 命令行的全体参数
※ 特殊变量示例
【例1-4】文件sh4的内容为
echo shell file is [$0] $0代表命令名
echo parameters are [$*] $*代表命令行(全体)参数
执行结果
$ sh4 a.c b.c 命令行参数为“a.c b.c”
shell file is [sh2] 第一个echo的结果
parameters are [a.c b.c] 第二个echo的结果
【例1-5】文件sh5的内容为
echo [$*]□□:□“[$2]□□[$1]” $2为第二个变量、$1为第一个变量
执行结果
$ sh5 36a1□□36a1.c
[36a1□36a1.c]□:□[36a1.c]□□[36a1]
shell对输出的空格采用以下原则:
输出命令中,无论在变量或者字符串之间有多少空格,输出时一律只取一个空格。例如,在以上冒号的两边空格数不相同,但是输出时都只有一个。在命令行的两个变量间有两个空格,输出时只产生一个,如[36a1□36a1.c]。如果需要输出多个空格,应该用引号括起空格。例如在“[$2]□□[$1]”中有两个空格,则将产生全部空格,输出[36a1.c]□□[36a1]。
【例1-6】文件sh6的内容为
echo compile $1.c
cc -o $1 $1.c
执行结果
$ sh6 34a1
compile 34a1.c
显示编译结果
【例1-7】文件sh7的内容为
echo $# files to be compiled $#代表命令行变量的数目
执行结果
$ sh7 36a1 36a2 36a3
3 files to be compiled
※ shell语句
在shell程序或者shell命令中可以使用的shell语句包括:
命令语句,赋值语句,结束语句,输入输出语句,运算语句以及移位命令各种控制结构语句等。
※ 命令语句
任何unix的shell命令或用户命令
※ 赋值语句
给变量赋值:
变量=值
撤销变量赋值:
变量=
※ 结束语句
exit
在shell命令行中表示撤消注册,或者可以使用logout命令。在shell程序中表示结束程序的执行。
※ 输入输出语句
read 变量 从stdin读取变量
echo 变量或字符串 向stdout输出变量或字符串
【例1-8】文件sh8的内容为
echo enter word:
read word
echo \\nword=$word 用\n产生换行
执行结果
$ sh8
enter word:
hello 用户输入数据
由\n产生的空行
word=hello 程序输出数据
【例1-9】echo语句的功能将产生换行。如果禁止换行,需要在行尾加\c。又因为\是特殊字符,需用反斜杠或者单引号转义。文件sh9为
echo enter 2 word:□\\c 用反斜杠\对\c转义
read w1
read w2
echo word1 is [${w1}], \ 用反斜杠\表示续行
word2 is [$w2] 本例${w1}和$w1的作用相同
执行结果
$ sh7
enter 2 words:□abc def
word1 is [abc], word2 is [def]
【例1-10】文件sh10
echo “new line?□\c”
echo “new line?□\\c”
echo ‘new line?□\c’
echo ‘new line?□\c’
请同学们运行sh10,并且归纳禁止换行和特殊字符的转义功能。
※ 运算语句
语句格式:
变量=`expr□表达式□运算符□表达式`
其中, 表达式由变量、常量和运算符组成
运算符包括+、-、*、/(整除)、%(取余)、==、!=、>、<、>=、<=、&(逻辑与)、|(逻辑或)等。运算符中如有特殊字符,须加反斜杠\转义。
``是一对反引号。表示执行expr的结果将作为变量的值。
【例1-11】文件sh11
echo enter 2 factors: \\c
read f1
read f2
p=`expr□$f1□\*□$f2` ``是一对反引号,\*将特殊字符*转义
echo $f1□“*”□$f2□=□$p 用“*”将特殊字符*转义
其中,命令expr是计算变量f1乘f2,由于一对反引号``(命令结果替换符)的作用,其计算结果将被作为数据赋值给变量p。
如果不将特殊字符*转义,其数值将是当前目录下的所有文件。
执行结果
$ sh11
enter 2 factors: 3 5
3 * 5 = 15
※ 移位命令
⊙ 移位命令的形式为:
shift
表示将传递到shell程序内部的命令行变量左移一位。
⊙ 例如,执行以下命令:
$ cmd v1 v2 v3 v4
则该命令传递到shell程序内部的命令行参数为
$# $0 $1 $2 $3 $4 $*
4 cmd v1 v2 v3 v4 v1 v2 v3 v4
若执行shift,则命令行参数变为
$# $0 $1 $2 $3 $*
3 cmd v2 v3 v4 v2 v3 v4
【例1-12】移位命令示例。文件sh12的内容为
echo Num=$# Var=$*
shift
echo Num=$# Var=$*
shift ; shift
echo Num=$# Var=$*
执行结果:
$ sh12 a bc d efg
Num=4 Var=a bc d efg
Num=3 Var=bc d efg
Num=1 Var=efg
【例1-13】shell程序sh12的改进示例一。把程序sh12改为sh13:
a="echo N=$# args=[$*]"
$a
shift ; $a
shift ; shift ; $a
【例1-14】shell程序sh12的改进示例二。
在Linux的Bash中,把命令赋值给变量然后执行是无效的。但是可以采用函数的方法。
把程序sh12改为sh14:
function a() 定义函数a
{
echo Num=$# var=$*
}
a() $* 调用函数a。在有的Linux中,不能加括号,改为:a $*
shift ; a() $* 调用函数a
shift ; shift
a() $* 调用函数a
其中,调用函数a时,将$*作为实参传递给函数a。从函数a的内部看,以同样的方式理解$#和$*,从而可以实现同样的功能。
※ 控制结构
※ 测试表达式
在if, for, while等控制结构中,需要使用测试表达式,以便确定执行不同的语句
⊙ 测试表达式的格式
[□表达式□] 在方括号与表达式之间必须要用空格分开
或者 test□表达式 在test与表达式之间必须用空格分开
表示如果表达式成立(表达式为真),则测试的结果为真,否则为假。
⊙ 字符串测试表达式
s1 = s2 字符串s1与s2相同时为真
s1 != s2 字符串s1与s2不相同时为真
-z s s是空字符串时为真
-n s s是非空字符串时为真
⊙ 关系运算表达式
s1 关系运算符 s2
可使用的关系运算符如下:
-eq 等于 -gt 大于 -ge 大于等于
-ne 不等于 -lt 小于 -le 小于等于
⊙ 文件测试表达式
-r file 文件file存在且可读
-w file 文件file存在且可写
-x file 文件file存在且可执行
-s file 文件file存在且非空
-d dir dir是一个目录
⊙ 逻辑运算表达式
! s1 非运算,若s1为真则“! s1”为假
s1 -a s2 与运算,若s1和s2都为真则为真
s1 -o s2 或运算,若s1和s2都为假则为假
※ if结构
if结构的格式为:
if [ 表达式 ]
then
语句组
else
语句组
fi
其中,可以省略else结构。
【例1-15】文件sh15
if [ $# -eq 0 ]
then
echo no args
else
echo args=$*
fi
执行:
$ sh15 以及
$ sh15 a bc def
结果分别是什么?
【例1-16】文件sh16
if [ ! -d $1 ]
then
echo $1 is not a directory
else
echo $1 is a directory
fi
假定只存在目录src和bin,执行:
$ sh16 ab src efg bin
结果是什么?
※ for 结构
for结构的格式为:
for 索引变量 in 变量表 变量表是一个参数的枚举表
do 从变量表中逐个获得索引变量的值
语句组
done
【例1-17】文件sh17
for i in $*
do
if [ ! -s $i ]
then
echo file $i is empty
fi
done
执行:
$ >a >file的作用是生成一个空文件file
$ cp $HOME/.profile profile
$ sh17 a profile
结果是什么?
【例1-18】文件sh18
for i in 0 1 2 3 4 5 6 7 8 9
do
for j in 0 1 2 3 4 5 6 7 8 9
do
> $i$j
done
done
执行:
$ sh18
结果是什么?
※ case 结构
case结构的格式为:
case 变量 in
情况1 ) 语句组 ;;
情况2 ) 语句组 ;;
…
* ) 语句组 ;;
esac
【例1-19】文件sh19
for i in $*
do
case $i in
*.c) echo $i is C file;;
*.o) echo $i is OBJ file;;
*) echo $i is unkown file;;
esac
done
执行:
$ sh19 36a1.o 36a1 36a1.c
结果是什么?
※ while 结构
while结构的格式为:
while [ 表达式 ]
do
语句组
done
【例1-20】改写sh19为sh20
while [ $# -gt 0 ]
do
case $1 in
*.c) echo $1 is C file;;
*.o) echo $1 is OBJ file;;
*) echo $1 is unkown file;;
esac
shift
done
⊙ 书中[例1-8]的改写(第31页)
[例1-8]:
改写结果:
#! /bin/sh
# File: makec
# Func : compile C source files
# Usage : makec name1 name2 …
# Files to be compiled: file =name.c
if test $# -eq 0
then
echo Usage: makec name1 name2 …
exit
fi
echo There are $# files …
while [ $# -gt 0 ]
do
cc -c $1.c 2> $1.err
if [ -s $1.err ]
then
echo see error in file $1.err
else
echo $1.c is OK!
fi
shift
done
#! /bin/sh
# File: makec
# Func : compile C source files
# Usage : makec name1 name2 …
# Files to be compiled: file =name.c
if test $# -eq 0
then
echo Usage: $0 name1 name2 …
exit
fi
echo There are $# files to be compiled
for i in $*
do
cc -c $i.c 2> $i.err
if [ -s $i.err ]
then
echo see error in file $i.err
else
echo $i.c is OK!
fi
done
作 业
※ 上机及习题,将运行结果写在作业本上
运行sh10, sh15, sh18, sh19, sh20 (\\fdme00下载)
(B shell程序)E-3: 1-20.1, 1-20.2
※ C语言编程练习 E-16:3-4(每周至少完成3题)
※ 阅读网络课堂“阅读材料”的以下文件,写一份shell简评(不超过200字),用邮件发给老师。
11-史蒂夫-伯恩
12-比尔-乔伊
13-大卫-科恩
展开阅读全文