linux脚本1
2009-01-13 16:41:12| 分类:
linux学习
| 标签:
|举报
|字号大中小 订阅
1. Linux 脚本编写基础
1.1 语法基本介绍
1.1.1 开头
程式必须以下面的行开始(必须方在文档的第一行):
#!/bin/sh
符号#!用来告诉系统他后面的参数是用来执行该文档的程式。在这个例子中我们使用/bin/sh来执行程式。
当编辑好脚本时,假如要执行该脚本,还必须使其可执行。
要使脚本可执行:
编译 chmod +x filename 这样才能用./filename 来运行
1.1.2 注释
在进行shell编程时,以#开头的句子表示注释,直到这一行的结束。我们真诚地建议您在程式中使用注释。
假如您使用了注释,那么即使相当长的时间内没有使用该脚本,您也能在很短的时间内明白该脚本的作用及工作原理。
1.1.3 变量
在其他编程语言中您必须使用变量。在shell编程中,任何的变量都由字符串组成,并且您无需对变量进行声明。要赋值给一个变量,您能够这样写:
#!/bin/sh
#对变量赋值:
a="hello world"
# 现在打印变量a的内容:
echo "A is:"
echo $a
有时候变量名很容易和其他文字混淆,比如:
num=2
echo "this is the $numnd"
这并不会打印出"this is the 2nd",而仅仅打印"this is the ",因为shell会去搜索变量numnd的值,但是这个变量时没有值的。能够使用花括号来告诉shell我们要打印的是num变量:
num=2
echo "this is the ${num}nd"
这将打印: this is the 2nd
1.1.4 环境变量
由export关键字处理过的变量叫做环境变量。我们不对环境变量进行讨论,因为通常情况下仅仅在登录脚本中使用环境变量。
1.1.5 Shell命令和流程控制
在shell脚本中能够使用三类命令:
1)Unix 命令:
虽然在shell脚本中能够使用任意的unix命令,但是还是由一些相对更常用的命令。这些命令通常是用来进行文档和文字操作的。
常用命令语法及功能
echo "some text": 将文字内容打印在屏幕上
ls: 文档列表
wc –l filewc -w filewc -c file: 计算文档行数计算文档中的单词数计算文档中的字符数
cp sourcefile destfile: 文档拷贝
mv oldname newname : 重命名文档或移动文档
rm file: 删除文档
grep 'pattern' file: 在文档内搜索字符串比如:grep 'searchstring' file.txt
cut -b colnum file: 指定欲显示的文档内容范围,并将他们输出到标准输出设备比如:输出每行第5个到第9个字符cut -b5-9 file.txt千万不要和cat命令混淆,
这是两个完全不同的命令
cat file.txt: 输出文档内容到标准输出设备(屏幕)上
file somefile: 得到文档类型
read var: 提示用户输入,并将输入赋值给变量
sort file.txt: 对file.txt文档中的行进行排序
uniq: 删除文本文档中出现的行列比如: sort file.txt | uniq
expr: 进行数学运算Example: add 2 and 3expr 2 "+" 3
find: 搜索文档比如:根据文档名搜索find . -name filename -print
tee: 将数据输出到标准输出设备(屏幕) 和文档比如:somecommand | tee outfile
basename file: 返回不包含路径的文档名比如: basename /bin/tux将返回 tux
dirname file: 返回文档所在路径比如:dirname /bin/tux将返回 /bin
head file: 打印文本文档开头几行
tail file : 打印文本文档末尾几行
sed: Sed是个基本的查找替换程式。能够从标准输入(比如命令管道)读入文本,并将
结果输出到标准输出(屏幕)。该命令采用正则表达式(见参考)进行搜索。不要和shell中的通配符相混淆。比如:将linuxfocus 替换为LinuxFocus :cat text.file | sed 's/linuxfocus/LinuxFocus/' > newtext.file awk: awk 用来从文本文档中提取字段。缺省地,字段分割符是空格,能够使用-F指定其他分割符。
cat file.txt | awk -F, '{print $1 "," $3 }'这里我们使用,作为字段分割符,同时打印第一个和第三个字段。假如该文档内容如下: Adam Bor, 34, IndiaKerry Miller, 22, USA命令输出结果为:Adam Bor, IndiaKerry Miller, USA
2) 概念: 管道, 重定向和 backtick
这些不是系统命令,但是他们真的很重要。
管道 (|) 将一个命令的输出作为另外一个命令的输入。
grep "hello" file.txt | wc -l
在file.txt中搜索包含有”hello”的行并计算其行数。
在这里grep命令的输出作为wc命令的输入。当然您能够使用多个命令。
重定向:将命令的结果输出到文档,而不是标准输出(屏幕)。
> 写入文档并覆盖旧文档
>> 加到文档的尾部,保留旧文档内容。
反短斜线
使用反短斜线能够将一个命令的输出作为另外一个命令的一个命令行参数。
命令:
find . -mtime -1 -type f -print
用来查找过去24小时(-mtime –2则表示过去48小时)内修改过的文档。假如您想将任何查找到的文档打一个包,则能够使用以下脚本:
#!/bin/sh
# The ticks are backticks (`) not normal quotes ('):
tar -zcvf lastmod.tar.gz `find . -mtime -1 -type f -print`
3) 流程控制
1.if
"if" 表达式 假如条件为真则执行then后面的部分:
if ....; then
....
elif ....; then
....
else
....
fi
大多数情况下,能够使用测试命令来对条件进行测试。比如能够比较字符串、判断文档是否存在及是否可读等等…
通常用" [ ] "来表示条件测试。注意这里的空格很重要。要确保方括号的空格。
[ -f "somefile" ] :判断是否是个文档
[ -x "/bin/ls" ] :判断/bin/ls是否存在并有可执行权限
[ -n "$var" ] :判断$var变量是否有值
[ "$a" = "$b" ] :判断$a和$b是否相等
执行man test能够查看任何测试表达式能够比较和判断的类型。
直接执行以下脚本:
#!/bin/sh
if [ "$SHELL" = "/bin/bash" ]; then
echo "your login shell is the bash (bourne again shell)"
else
echo "your login shell is not bash but $SHELL"
fi
变量$SHELL包含了登录shell的名称,我们和/bin/bash进行了比较。
快捷操作符
熟悉C语言的朋友可能会很喜欢下面的表达式:
[ -f "/etc/shadow" ] && echo "This computer uses shadow passwors"
这里 && 就是个快捷操作符,假如左边的表达式为真则执行右边的语句。
您也能够认为是逻辑运算中的和操作。上例中表示假如/etc/shadow文档存在则打印” This computer uses shadow passwors”。同样或操作(||)在shell编程中也是可用的。这里有个例子:
#!/bin/sh
mailfolder=/var/spool/mail/james
[ -r "$mailfolder" ]' '{ echo "Can not read $mailfolder" ; exit 1; }
echo "$mailfolder has mail from:"
grep "^From " $mailfolder
该脚本首先判断mailfolder是否可读。假如可读则打印该文档中的"From" 一行。假如不可读则或操作生效,打印错误信息后脚本退出。这里有个问题,那就是我们必须有两个命令:
-打印错误信息
-退出程式
我们使用花括号以匿名函数的形式将两个命令放到一起作为一个命令使用。一般函数将在下文提及。
不用和和或操作符,我们也能够用if表达式作任何事情,但是使用和或操作符会更便利很多。
2.case
case :表达式能够用来匹配一个给定的字符串,而不是数字。
case ... in
...) do something here ;;
esac
让我们看一个例子。 file命令能够辨别出一个给定文档的文档类型,比如:
file lf.gz
这将返回:
lf.gz: gzip compressed data, deflated, original filename,
last modified: Mon Aug 27 23:09:18 2001, os: Unix
我们利用这一点写了一个叫做smartzip的脚本,该脚本能够自动解压bzip2, gzip 和zip 类型的压缩文档:
#!/bin/sh
ftype=`file "$1"`
case "$ftype" in
"$1: Zip archive"*)
unzip "$1" ;;
"$1: gzip compressed"*)
gunzip "$1" ;;
"$1: bzip2 compressed"*)
bunzip2 "$1" ;;
*) echo "File $1 can not be uncompressed with smartzip";;
esac
您可能注意到我们在这里使用了一个特别的变量$1。该变量包含了传递给该程式的第一个参数值。
也就是说,当我们运行:
smartzip articles.zip
$1 就是字符串 articles.zip
3. selsect
select 表达式是一种bash的扩展应用,尤其擅长于交互式使用。用户能够从一组不同的值中进行选择。
select var in ... ; do
break
done
.... now $var can be used ....
下面是个例子:
#!/bin/sh
echo "What is your favourite OS?"
select var in "Linux" "Gnu Hurd" "Free BSD" "Other"; do
break
done
echo "You have selected $var"
下面是该脚本运行的结果:
What is your favourite OS?
1) Linux
2) Gnu Hurd
3) Free BSD
4) Other
#? 1
You have selected Linux
4.loop
loop表达式:
while ...; do
....
done
while-loop 将运行直到表达式测试为真。will run while the expression that we test for is true.
关键字"break" 用来跳出循环。而关键字”continue”用来不执行余下的部分而直接跳到下一个循环。
for-loop表达式查看一个字符串列表 (字符串用空格分隔) 然后将其赋给一个变量:
for var in ....; do
....
done
在下面的例子中,将分别打印ABC到屏幕上:
#!/bin/sh
for var in A B C ; do
echo "var is $var"
done
下面是个更为有用的脚本showrpm,其功能是打印一些RPM包的统计信息:
#!/bin/sh
# list a content summary of a number of RPM packages
# USAGE: showrpm rpmfile1 rpmfile2 ...
# EXAMPLE: showrpm /cdrom/RedHat/RPMS/*.rpm
for rpmpackage in $*; do
if [ -r "$rpmpackage" ];then
echo "=============== $rpmpackage =============="
rpm -qi -p $rpmpackage
else
echo "ERROR: cannot read file $rpmpackage"
fi
done
这里出现了第二个特别的变量$*,该变量包含了任何输入的命令行参数值。
假如您运行showrpm openssh.rpm w3m.rpm webgrep.rpm
此时 $* 包含了 3 个字符串,即openssh.rpm, w3m.rpm and webgrep.rpm.
5. 引号
在向程式传递任何参数之前,程式会扩展通配符和变量。这里所谓扩展的意思是程式会把通配符(比如*)替换成合适的文档名,他变量替换成变量值。为了防止程式作这种替换,您能够使用引号:让我们来看一个例子,假设在当前目录下有一些文档,两个jpg文档, mail.jpg 和tux.jpg。
1.2 编译SHELL脚本
#ch#!/bin/sh mod +x filename
cho *.jpg ∪缓螅梢酝ü淙耄?./filename 来执行您的脚本。
这将打印出"mail.jpg tux.jpg"的结果。
引号 (单引号和双引号) 将防止这种通配符扩展:
#!/bin/sh
echo "*.jpg"
echo '*.jpg'
这将打印"*.jpg" 两次。
单引号更严格一些。他能够防止任何变量扩展。双引号能够防止通配符扩展但允许变量扩展。
#!/bin/sh
echo $SHELL
echo "$SHELL"
echo '$SHELL'
运行结果为:
/bin/bash
/bin/bash
$SHELL
最后,更有一种防止这种扩展的方法,那就是使用转义字符——反斜杆:
echo *.jpg
echo $SHELL
这将输出:
*.jpg
$SHELL
6. Here documents
当要将几行文字传递给一个命令时,here documents(译者注:现在还没有见到过对该词适合的翻译)一种不错的方法。对每个脚本写一段帮助性的文字是很有用的,此时假如我们四有那个 here documents就不必用echo函数一行行输出。 一个 "Here document" 以
4)函数
假如您写了一些稍微复杂一些的程式,您就会发现在程式中可能在几个地方使用了相同的代码,并且您也会发现,假如我们使用了函数,会方便很多。一个函数是这个样子的:
functionname()
{
# inside the body $1 is the first argument given to the function
# $2 the second ...
body
}
您需要在每个程式的开始对函数进行声明。
下面是个叫做xtitlebar的脚本,使用这个脚本您能够改变终端窗口的名称。
这里使用了一个叫做help的函数。正如您能够看到的那样,这个定义的函数被使用了两次。
#!/bin/sh
# vim: set sw=4 ts=4 et:
help()
{
cat shift by 2
--) shift;break;; # end of options
-*) echo "error: no such option $1. -h for help";exit 1;;
*) break;;
esac
done
echo "opt_f is $opt_f"
echo "opt_l is $opt_l"
echo "first arg is $1"
echo "2nd arg is $2"
您能够这样运行该脚本:
cmdparser -l hello -f -- -somefile1 somefile2
返回的结果是:
opt_f is 1
opt_l is hello
first arg is -somefile1
2nd arg is somefile2
这个脚本是如何工作的呢?脚本首先在任何输入命令行参数中进行循环,将输入参数和case表达式进行比较,假如匹配则配置一个变量并且移除该参数。根据unix系统的惯例,首先输入的应该是包含减号的参数.
第2部分 实例
现在我们来讨论编写一个脚本的一般步骤。任何优秀的脚本都应该具备帮助和输入参数。并且写一个伪脚本(framework.sh),该脚本包含了大多数脚本都需要的框架结构,是个很不错的主意。这时候,在写一个新的脚本时我们只需要执行一下copy命令:
cp framework.sh myscript
然后再插入自己的函数。
让我们再看两个例子:
二进制到十进制的转换
脚本 b2d 将二进制数 (比如 1101) 转换为相应的十进制数。这也是个用expr命令进行数学运算的例子:
#!/bin/sh
# vim: set sw=4 ts=4 et:
help()
{
cat
--------------------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------------------
shell编程简介
作者: 何斌武 (
hbwork@dlut.edu.cn
,大连理工大学网络中央,April 1999.)
Bourne Shell
介绍:Bourne Shell 基础及其他很多有用的特性,shell编程及组织。
主要内容:
.shell基础 基本介绍,环境,选项,特别字符
.shell变量 用户定义变量,环境变量,位置变量(shell 参数)
.shell script编程
条件测试,循环及重复控制
.shell定制
1.shell基础知识
作者:Stephen Bourne 在Bell实验室研发
建议:man sh 查看相关UNIX上的改进或特性
(1)shell提示符及其环境
/etc/passwd文档
提示符:$
/etc/profile $HOME/.profile
(2)shell执行选项
-n 测试shell script语法结构,只读取shell script但不执行
-x 进入跟踪方式,显示所执行的每一条命令,用于调度
-a Tag all variables for export
-c "string" 从strings中读取命令
-e 非交互方式
-f 关闭shell文档名产生功能
-h locate and remember functions as defind
-i 交互方式
-k 从环境变量中读取命令的参数
-r 限制方式
-s 从标准输入读取命令
-t 执行命令后退出(shell exits)
-u 在替换中如使用未定义变量为错误
-v verbose,显示shell输入行
这些选项能够联合使用,但有些显然相互冲突,如-e和-i.
(3)受限制shell(Restircted Shell)
sh -r 或 /bin/rsh
不能执行如下操作:cd, 更改PATH,指定全路径名,输出重定向,因此能够提供一个较
好的控制和安全机制。通常rsh用于应用型用户及拨号用户,这些用户通常是看不到提
示符的。通常受限制用户的主目录是不可写的。
不足:假如用户能够调用sh,则rsh的限制将不在起作用,事实上假如用户在vi及more
程式中调用shell,而这时rsh的限制将不再起作用。
(4)用set改变 shell选项
用户能够在$提示符下用set命令来配置或取消shell的选项。使用-配置选项,+取消相应
选项,大多数UNIX系统允许a,e,f,h,k,n,u,v和x的开关配置/取消。
set -xv
启动跟踪方式;显示任何的命令及替换,同样显示输入。
set -tu
关闭在替换时对未定义变量的检查。
使用echo $-显示任何已配置的shell选项。
(5)用户启动文档 .profile
PATH=$PATH:/usr/loacl/bin; export PATH
(6)shell环境变量
CDPATH 用于cd命令的查找路径
HOME /etc/passwd文档中列出的用户主目录
IFS Internal Field Separator,默认为空格,tab及换行符
MAIL /var/mail/$USERNAME mail等程式使用
PATH
PS1,PS2 默认提示符($)及换行提示符(>)
TERM 终端类型,常用的有vt100,ansi,vt200,xterm等
示例:$PS1="test:";export PS1
test: PS1="\$";export PS1
$echo $MAIL
/var/mail/username
(7)保留字符及其含义
$ shell变量名的开始,如$var
| 管道,将标准输出转到下一个命令的标准输入
# 注释开始
& 在后台执行一个进程
? 匹配一个字符
* 匹配0到多个字符(和DOS不同,可在文档名中间使用,并且含.)
$- 使用set及执行时传递给shell的标志位
$! 最后一个子进程的进程号
$# 传递给shell script的参数个数
$* 传递给shell script的参数
$@ 任何参数,个别的用双引号括起来
$? 上一个命令的返回代码
$0 当前shell的名字
$n (n:1-) 位置参数
$$ 进程标识号(Process Identifier Number, PID)
>file 输出重定向
`command` 命令替换,如 filename=`basename /usr/local/bin/tcsh`
>>fiile 输出重定向,append
转义符及单引号:
$echo "$HOME $PATH"
/home/hbwork /opt/kde/bin:/usr/local/bin:/bin:/usr/bin:/usr/X11R6/bin:
$echo '$HOME $PATH'
$HOME $PATH
$echo \$HOME $PATH
$HOME /opt/kde/bin:/usr/local/bin:/bin:/usr/bin:/usr/X11R6/bin:/home/hbwork/bin
其他:
$dir=ls
$$dir
$alias dir ls
$dir
ls > filelist
ls >> filelist
wc -l
2. shell变量
变量:代表某些值的符号,如$HOME,cd命令查找$HOME,在电脑语言中能够使用变量能够
进行多种运算和控制。
Bourne Shell有如下四种变量:
.用户自定义变量
.位置变量即 shell script之参数
.预定义变量(特别变量)
.环境变量(参考shell定制部分)
(1)用户自定义变量(数据的存储)
$ COUNT=1
$ NAME="He Binwu"
技巧:因为大部分UNIX命令使用小写字符,因此在shell编程中通常使用全大写变量,
当然这并不是强制性的,但使用大写字符能够在编程中方便地识别变量。
变量的调用:在变量前加$
$ echo $HOME
/home/hbwork
$ WEEK=Satur
$ echo Today is $WEEKday
Today is
$echo Today is ${WEEK}day
Today is Saturday
Shell变量赋值从右从左进行(Linux Shell/bash从左向右赋值!)
$ X=$Y Y=y
$ echo $X
y
$ Z=z Y=$Z
$ echo $Y
$
使用unset命令删除变量的赋值
$ Z=hello
$ echo $Z
hello
$ unset Z
$ echo $Z
$
有条件的命令替换
在Bourne Shell中能够使变量替换在特定条件下执行,即有条件的环境变量替换。
这种变量替换总是用大括号括起来的。
.配置变量的默认值
在变量未赋值之前其值为空。Bourne Shell允许对变量配置默认值,其格式如下:
${variable:-defaultvalue}
例:
$ echo Hello $UNAME
Hello
$ echo Hello ${UNAME:-there}
Hello there
$ echo $UNAME #变量值并未发生变化
$ UNAME=hbwork
$ echo Hello ${UNAME:-there}
Hello hbwork
$
.另一种情况:改变变量的值,格式如下:
${variable:=value}
例:
$ echo Hello $UNAME
Hello
$ echo Hello ${UNAME:=there}
Hello there
$ echo $UNAME #变量值并未发生变化
there
$
.变量替换中使用命令替换
$USERDIR=${$MYDIR:-`pwd`}
.在变量已赋值时进行替换 ${variable:+value}
.带有错误检查的有条件变量替换
${variable:?value}
例:
$ UNAME=
$ echo ${UNAME:?"UNAME has not been set"}
UNAME: UNAME has not been set
$ echo ${UNAME:?}
UNAME: parameter null or not set
(2)位置变量(Shell参数)
在shell script中位置参数可用$1..$9表示,$0表示内容通常为当前执行程式的文档名。
.防止变量值被替换 readonly variable
.使用export命令输出变量,使得变量对子shell可用,当shell执行一下程式时,shell
将为其配置一个新的环境让其执行,这称之了subshell. 在Bourne Shell中变量通常
被认为是本地变量,也就是说在对其赋值之外的shell环境之外是不认识此变量的。使
用export对subshell可用。
例:对变量PS1的export操作,shell的提示符将发生变化。
$ PS1=`hostname`$
peony$sh
$ echo $PS1
$
3.Shell Script编程
目的:使用UNIX所提供的最常用工具来完成所需复杂任务的强大功能。
(1)最简单的Shell 编程
$ls -R / |grep myname |more
每天数据的备份:
$ cd /usr/yourname; ls * |cpio -o > /dev/rmt/0h
书写程式的目的是一次编程,多次使用(执行)!
$ cat > backup.sh
cd /home/hbwork
ls * | cpio -o > /dev/rmt/0h
^D
执行:
$ sh backup.sh
或:
$ chmod +x backup.sh
$ ./backup.sh
技巧:在shell script中加入必要的注释,以便以后阅读及维护。
(2)shell是个(编程)语言
同传统的编程语言相同,shell提供了很多特性,这些特性能够使您的shell script
编程更为有用,如:数据变量、参数传递、判断、流程控制、数据输入和输出,子
程式及以中断处理等。
. 在shell编程中使用数据变量能够将程式变量更为通用,如在上面backup.sh中:
cd $WORKDIR
ls * | cpio -o > /dev/rmt/0h
. Shell编程中的注释以#开头
. 对shell变量进行数字运算,使用expr命令
expr integer operator integer
其中operator为+ - * / %, 但对*的使用要用转义符\,如:
$expr 4 \* 5
20
$int=`expr 5 + 7`
$echo $int
12
(3)Shell编程的参数传递, 可通过命令行参数连同交互式输入变量(read)
restoreall.sh 对backup.sh程式的备份磁带进行恢复
$cat > restoreall.sh
cd $WORKDIR
cpio -i
$restore1 file1
恢复多个文档restoreany :
#restoreany --program to restore a single file
cd $WORKDIR
cpio -i $*
$ restoreany file1 file2 file3
(4)条件判断
. if-then语句,格式如下:
if command_1
then
command_2
command_3
fi
command_4
在if-then语句中使用了命令返回码$?,即当command_1执行成功时才执行command_2和
command_3,而command_4总是执行.
示例程式unload: 在备份成功时删除原始文档,带有错误检查
cd $1
#备份时未考虑不成功的情况!
ls -a | cpio -o > /dev/rmt/0h
rm -rf *
改进如下:
#当使用了管道命令时,管理命令的返回代码为最后一个命令的返回代码
if ls -a | cpio -o > /dev/rmt/0h
then
rm -rf *
fi
. if-then-else语句
if command_1
then
command_2
else
command_3
fi
技巧: 由于shell对命令中的多余的空格不作任何处理,一个好的程式员会用这一特性
对自己的程式采用统一的缩进格式,以增强自己程式的可读性.
. 使用test命令进行进行条件测试
格式: test conditions
test在以下四种情况下使用: a. 字符比较 b.两个整数值的比较
c. 文档操作,如文档是否存在及文档的状态等
d. 逻辑操作,能够进行and/or,和其他条件联合使用
a. 测试字符数据: shell变量通常民政部下均作为字符变量
str1 = str2 二者相长,相同
str1 != str2 不同
-n string string不为空(长度不为零)
-z string string为空
string string不为空
例:
$ str1=abcd #在含有空格时必须用引号括起来
$ test $str1=abcd
$ echo $?
0
$ str1="abcd "
$ test $str1=abcd
$ echo $?
1
Note: 在test处理含有空格的变量时最好用引号将变量括起来,否则会出现错误的结果,
因为shell在处理命令行时将会去掉多余的空格,而用引号括起来则能够防止
shell去掉这些空格.
例:
$ str1=" "
$ test $str1
$ echo $?
1
$ test "$str1"
$ echo $?
0
$ test -n $str1
test: argument expected
$ test -n "$str1"
$ echo $?
0
$
b. 整数测试: test和expr相同,能够将字符型变量转换为整数进行操作,expr进行
整数的算术运算,而test则进行逻辑运算.
表达式 说明
---------------------------------------
int1 -eq int2 相等?
int1 -ne int2 不等?
int1 -gt int2 int1 > int2 ?
int1 -ge int2 int1 >= int2 ?
int1 -lt int2 int1
例:
$ int1=1234
$ int2=01234
$ test $int1 -eq $int2
$ echo $?
0
c. 文档测试:检查文档状态如存在及读写权限等
-r filename 用户对文档filename有读权限?
-w filename 用户对文档filename有写权限?
-x filename 用户对文档filename有可执行权限?
-f filename 文档filename为普通文档?
-d filename 文档filename为目录?
-c filename 文档filename为字符设备文档?
-b filename 文档filename为块设备文档?
-s filename 文档filename大小不为零?
-t fnumb 和文档描述符fnumb(默认值为1)相关的设备是个终端设备?
d. 测试条件之否定,使用!
例:
$ cat /dev/null > empty
$ test -r empty
$ echo $?
0
$ test -s empty
1
$ test ! -s empty
$ echo $?
0
e. 测试条件之逻辑运算
-a And
-o Or
例: $ test -r empty -a -s empty
$ echo $?
1
f. 进行test测试的标准方法
因为test命令在 shell编程中占有很重要的地位,为了使shell能同其他编程语言相同
便于阅读和组织, Bourne Shell在使用test测试时使用了另一种方法:用方括号将整个
test测试括起来:
$ int1=4
$ [ $int1 -gt 2 ]
$ echo $?
0
例: 重写unload程式,使用test测试
#!/bin/sh
#unload - program to backup and remove files
#syntax: unload directory
#check arguments
if [ $# -ne 1 ]
then
echo "usage: $0 directory"
exit 1
fi
#check for valid directory name
if [ ! -d "$1" ]
then
echo "$1 is not a directory"
exit 2
fi
cd $1
ls -a | cpio -o > /dev/rmt/0h
if [ $? -eq 0 ]
then
rm -rf *
else
echo "A problem has occured in creating backup"
echo "The directory will not be ereased"
echo "Please check the backup device"
exit 3
fi
# end of unload
在如上示例中出现了exit, exit有两个作用:一是停止程式中其他命令的执行,二是
配置程式的退出状态
g. if嵌套及elif结构
if command
then
command
else
if command
then
command
else
if command
then
command
fi
fi
fi
改进:使用elif结构
if command
then
command
elif command
then
command
elif command
then
command
fi
elif结构同if结构类似,但结构更清淅,其执行结果完全相同.
h.交互式从键盘读入数据
使用read语句,其格式如下:
read var1 var2 ... varn
read将不作变量替换,但会删除多余的空格,直到碰到第一个换行符(回车),
并将输入值依次赋值给相应的变量。
例:
$ read var1 var2 var3
Hello my friends
$ echo $var1 $var2 $var3
Hello my friends
$ echo $var1
Hello
$ read var1 var2 var3
Hello my dear friends
$ echo $var3
dear friends
在shell script中可使用read语句进行交互操作:
...
#echo -n message 输出结果后不换行
echo -n "Do you want to continue: Y or N"
read ANSWER
if [ $ANSWER=N -o $ANSWER=n ]
then
exit
fi
i. case结构:结构较elif-then结构更清楚
比较if-then语句:
if [ variable1 = value1 ]
then
command
command
elif [ variable1 = value2 ]
then
command
command
elif [ variable1 = value3 ]
then
command
command
fi
相应的case结构:
case value in
pattern1)
command
command;;
pattern2)
command
command;;
...
patternn)
command;
esac
* case语句只执行第一个匹配模式
例:使用case语句建立一个菜单选择shell script
#Dlay a menu
echo _
echo "1 Restore"
echo "2 Backup"
echo "3 Unload"
echo
#Read and excute the user's selection
echo -n "Enter Choice:"
read CHOICE
case "$CHOICE" in
1) echo "Restore";;
2) echo "Backup";;
3) echo "Unload";;
*) echo "Sorry $CHOICE is not a valid choice
exit 1
esac
评论这张
转发至微博
转发至微博
评论