在第十一章中,我们提到过 [color=red]$?[/color] 这个变量所代表的意义, 此外,也透过 && 及 || 来作为前一个命令运行回传值对於后一个命令是否要进行的依据。第十一章的讨论中,如果想要判断一个目录是否存在, 当时我们使用的是 ls 这个命令搭配数据流重导向,最后配合 $? 来决定后续的命令进行与否。 但是否有更简单的方式可以来进行『条件判断』呢?有的~那就是[color=red]『 test 』[/color]这个命令。
[size=large][b]利用 test 命令的测试功能[/b][/size]
当我要检测系统上面某些文件或者是相关的属性时,利用 test 这个命令来工作真是好用得不得了, 举例来说,我要检查 /dmtsai 是否存在时,使用:
[code="linux"]
# test -e /dmtsai
[/code]
运行结果并不会显示任何信息,但最后我们可以透过 $? 或 && 及 || 来展现整个结果呢! 例如我们在将上面的例子改写成这样:
[code="linux"]
# test -e /dmtsai && echo "exist" || echo "Not exist"
Not exist <==结果显示不存在啊!
[/code]
最终的结果可以告知我们是『exist』还是『Not exist』呢!那我知道[color=red] -e [/color]是测试一个『东西』在不在, 如果还想要测试一下该档名是啥玩意儿时,还有哪些标志可以来判断的呢?呵呵!有底下这些东西喔!
测试的标志 代表意义
[color=red]1. 关於某个档名的『文件类型』判断,如 test -e filename 表示存在否[/color]
-e 该『档名』是否存在?(常用)
[color=blue]-f 该『档名』是否存在且为文件(file)?(常用)[/color]
[color=blue]-d 该『档名』是否存在且为目录(directory)?(常用)[/color]
-b 该『档名』是否存在且为一个 block device 装置?
-c 该『档名』是否存在且为一个 character device 装置?
-S 该『档名』是否存在且为一个 Socket 文件?
-p 该『档名』是否存在且为一个 FIFO (pipe) 文件?
-L 该『档名』是否存在且为一个连结档?
[color=red]2. 关於文件的权限侦测,如 test -r filename 表示可读否 (但 root 权限常有例外)[/color]
-r 侦测该档名是否存在且具有『可读』的权限?
-w 侦测该档名是否存在且具有『可写』的权限?
-x 侦测该档名是否存在且具有『可运行』的权限?
-u 侦测该档名是否存在且具有『SUID』的属性?
-g 侦测该档名是否存在且具有『SGID』的属性?
-k 侦测该档名是否存在且具有『Sticky bit』的属性?
-s 侦测该档名是否存在且为『非空白文件』?
[color=red]3. 两个文件之间的比较,如: test file1 -nt file2[/color]
-nt (newer than)判断 file1 是否比 file2 新
-ot (older than)判断 file1 是否比 file2 旧
-ef 判断 file1 与 file2 是否为同一文件,可用在判断 hard link 的判定上。 主要意义在判定,两个文件是否均指向同一个 inode 哩!
[color=red]4. 关於两个整数之间的判定,例如 test n1 -eq n2[/color]
-eq 两数值相等 (equal)
-ne 两数值不等 (not equal)
[color=red]-gt n1 大於 n2 (greater than)[/color]
-lt n1 小於 n2 (less than)
-ge n1 大於等於 n2 (greater than or equal)
-le n1 小於等於 n2 (less than or equal)
5. 判定字串的数据
test -z string 判定字串是否为 0 ?若 string 为空字串,则为 true
test -n string 判定字串是否非为 0 ?若 string 为空字串,则为 false。
注: -n 亦可省略
test str1 = str2 判定 str1 是否等於 str2 ,若相等,则回传 true
test str1 != str2 判定 str1 是否不等於 str2 ,若相等,则回传 false
[color=red]6. 多重条件判定,例如: test -r filename -a -x filename[/color]
-a (and)两状况同时成立!例如 test -r file -a -x file,则 file 同时具有 r 与 x 权限时,才回传 true。
-o (or)两状况任何一个成立!例如 test -r file -o -x file,则 file 具有 r 或 x 权限时,就可回传 true。
! 反相状态,如 test ! -x file ,当 file 不具有 x 时,回传 true
OK!现在我们就利用 test 来帮我们写几个简单的例子。首先,判断一下,让使用者输入一个档名,我们判断:
这个文件是否存在,若不存在则给予一个『Filename does not exist』的信息,并中断程序;
若这个文件存在,则判断他是个文件或目录,结果输出『Filename is regular file』或 『Filename is directory』
判断一下,运行者的身份对这个文件或目录所拥有的权限,并输出权限数据!
你可以先自行创作看看,然后再跟底下的结果讨论讨论。注意利用 test 与 && 还有 || 等标志!
[code="linux"]
# vi sh05.sh
#!/bin/bash
# Program:
# User input a filename, program will check the flowing:
# 1.) exist? 2.) file/directory? 3.) file permissions
# History:
# 2005/08/25 VBird First release
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
# 1. 让使用者输入档名,并且判断使用者是否真的有输入字串?
echo -e "Please input a filename, I will check the filename's type and \
permission. \n\n"
read -p "Input a filename : " filename
test -z $filename && echo "You MUST input a filename." && exit 0
# 2. 判断文件是否存在?若不存在则显示信息并结束脚本
test ! -e $filename && echo "The filename '$filename' DO NOT exist" && exit 0
# 3. 开始判断文件类型与属性
test -f $filename && filetype="regulare file"
test -d $filename && filetype="directory"
test -r $filename && perm="readable"
test -w $filename && perm="$perm writable"
test -x $filename && perm="$perm executable"
# 4. 开始输出资讯!
echo "The filename: $filename is a $filetype"
echo "And the permissions are : $perm"
[/code]
如果你运行这个脚本后,他会依据你输入的档名来进行检查喔![color=red]先看是否存在,再看为文件或目录类型,最后判断权限。[/color] 但是你必须要注意的是,由於 root 在很多权限的限制上面都是无效的,所以使用 root 运行这个脚本时, 常常会发现与 ls -l 观察到的结果并不相同!所以,建议使用一般使用者来运行这个脚本试看看。 不过你必须要使用 root 的身份先将这个脚本搬移给使用者就是了,不然一般使用者无法进入 /root 目录的。 很有趣的例子吧!你可以自行再以其他的案例来撰写一下可用的功能呢!
[size=large][b]利用判断符号 [ ][/b][/size]
除了我们很喜欢使用的 test 之外,[color=red]其实,我们还可以利用判断符号『 [ ] 』(就是中括号啦) 来进行数据的判断[/color]呢! 举例来说,如果我想要知道 $HOME 这个变量是否为空的,可以这样做:
[code="linux"]
# [ -z "$HOME" ] ; echo $?
[/code]
使用中括号必须要特别注意,因为中括号用在很多地方,包括万用字节与正规表示法等等,所以如果要在 bash 的语法当中使用中括号作为 shell 的判断式时,必须要注意中括号的两端需要有空白字节来分隔喔! 假设我空白键使用『□』符号来表示,那么,在这些地方你都需要有空白键:
[color=red]上面的例子在说明,两个字串 $HOME 与 $MAIL 是否相同的意思,相当於 test $HOME = $MAIL 的意思啦![/color] 而如果没有空白分隔,[color=red]例如 [$HOME==$MAIL] 时,我们的 bash 就会显示错误信息了![/color]这可要很注意啊! 所以说,你最好要注意:
[color=red]A 在中括号 [] 内的每个组件都需要有空白键来分隔;[/color]
[color=blue]B 在中括号内的变量,最好都以双引号括号起来;[/color]
[color=blue]C 在中括号内的常数,最好都以单或双引号括号起来。[/color]
为什么要这么麻烦啊?直接举例来说,假如我配置了 name="VBird Tsai" ,然后这样判定:
[code="linux"]
# name="VBird Tsai"
# [ $name == "VBird" ]
bash: [: too many arguments
[/code]
见鬼了!怎么会发生错误啊?bash 还跟我说错误是由於『太多参数 (arguments)』所致! 为什么呢?[color=red]因为 $name 如果没有使用双引号刮起来,那么上面的判定式会变成:[/color]
[ VBird Tsai == "VBird" ]
上面肯定不对嘛!因为一个判断式仅能有两个数据的比对,上面 VBird 与 Tsai 还有 "VBird" 就有三个数据! 这不是我们要的!我们要的应该是底下这个样子:
[ "VBird Tsai" == "VBird" ]
这可是差很多的喔!另外,[color=red]中括号的使用方法与 test 几乎一模一样啊[/color]~ [color=red]只是中括号比较常用在条件判断式 if ..... then ..... fi 的情况中就是了。[/color] 好,那我们也使用中括号的判断来做一个小案例好了,案例配置如下:
当运行一个程序的时候,这个程序会让使用者选择 Y 或 N ,
如果使用者输入 Y 或 y 时,就显示『 OK, continue 』
如果使用者输入 n 或 N 时,就显示『 Oh, interrupt !』
如果不是 Y/y/N/n 之内的其他字节,就显示『 I don't know what your choice is 』
利用中括号、 && 与 || 来继续吧!
[code="linux"]
# vi sh06.sh
#!/bin/bash
# Program:
# This program shows the user's choice
# History:
# 2005/08/25 VBird First release
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
read -p "Please input (Y/N): " yn
[ "$yn" == "Y" -o "$yn" == "y" ] && echo "OK, continue" && exit 0
[ "$yn" == "N" -o "$yn" == "n" ] && echo "Oh, interrupt!" && exit 0
echo "I don't know what your choice is" && exit 0
[/code]
由於输入正确 (Yes) 的方法有大小写之分,不论输入大写 Y 或小写 y 都是可以的,此时判断式内就得要有两个判断才行! 由於是任何一个成立即可 (大小或小写的 y) ,所以这里使用 [color=red]-o (或)[/color] 连结两个判断喔! 很有趣吧!利用这个字串判别的方法,我们就可以很轻松的将使用者想要进行的工作分门别类呢! 接下来,我们再来谈一些其他有的没有的东西吧!
[size=large][b]Shell script 的默认变量($0, $1...)[/b][/size]
我们知道命令可以带有选项与参数,例如 ls -la 可以察看包含隐藏档的所有属性与权限。那么 shell script [color=red]能不能在脚本档名后面带有参数呢?[/color]很有趣喔!举例来说,如果你想要重新启动系统登录档的功能,可以这样做:
[code="linux"]
# file /etc/init.d/syslog
/etc/init.d/syslog: Bourne-Again shell script text executable
# 使用 file 来查询后,系统告知这个文件是个 bash 的可运行 script 喔!
# /etc/init.d/syslog restart[/code]
restart 是重新启动的意思,上面的命令可以『重新启动 /etc/init.d/syslog 这支程序』的意思! 唔!那么如果你在 /etc/init.d/syslog 后面加上 stop 呢?没错!就可以直接关闭该服务了!这么神奇啊? 没错啊!如果你要依据程序的运行给予一些变量去进行不同的任务时,本章一开始是使用 read 的功能!但 read 功能的问题是你得要手动由键盘输入一些判断式。如果透过命令后面接参数, 那么一个命令就能够处理完毕而不需要手动再次输入一些变量行为!这样下达命令会比较简单方便啦!
script 是怎么达成这个功能的呢?其实 script 针对参数已经有配置好一些变量名称了!对应如下:
这样够清楚了吧?[color=red]运行的脚本档名为 $0 这个变量,第一个接的参数就是 $1 啊[/color]~ 所以,只要我们在 script 里面善用 $1 的话,就可以很简单的立即下达某些命令功能了!除了这些数字的变量之外, 我们还有一些较为特殊的变量可以在 script 内使用来呼叫这些参数喔!
[color=red]$# :代表后接的参数『个数』,以上表为例这里显示为『 4 』[/color];
[color=red]$@ :代表『 "$1" "$2" "$3" "$4" 』之意,每个变量是独立的(用双引号括起来);[/color]
[color=blue]$* :代表『 "$1c$2c$3c$4" 』,其中 c 为分隔字节,默认为空白键, 所以本例中代表『 "$1 $2 $3 $4" 』之意。[/color]
那个 $@ 与 $* 基本上还是有所不同啦!不过,一般使用情况下可以直接记忆 $@ 即可! 好了,来做个例子吧~假设我要运行一个可以携带参数的 script ,运行该脚本后萤幕会显示如下的数据:
程序的档名为何?
共有几个参数?
若参数的个数小於 2 则告知使用者参数数量太少
全部的参数内容为何?
第一个参数为何?
第二个参数为何
[code="linux"]
# vi sh07.sh
#!/bin/bash
# Program:
# Program shows the script name, parameters...
# History:
# 2009/02/17 VBird First release
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
echo "The script name is ==> $0"
echo "Total parameter number is ==> $#"
[ "$#" -lt 2 ] && echo "The number of parameter is less than 2. Stop here." \
&& exit 0
echo "Your whole parameter is ==> '$@'"
echo "The 1st parameter ==> $1"
echo "The 2nd parameter ==> $2"
[/code]
运行结果如下:
[code="linux"]
# sh sh07.sh theone haha quot
The script name is ==> sh07.sh <==档名
Total parameter number is ==> 3 <==果然有三个参数
Your whole parameter is ==> 'theone haha quot' <==参数的内容全部
The 1st parameter ==> theone <==第一个参数
The 2nd parameter ==> haha <==第二个参数
[/code]
[size=small][b]shift:造成参数变量号码偏移[/b][/size]
除此之外,脚本后面所接的变量是否能够进行偏移 (shift) 呢?什么是偏移啊?我们直接以底下的范例来说明好了, 用范例说明比较好解释!我们将 sh07.sh 的内容稍作变化一下,用来显示每次偏移后参数的变化情况:
[code="linux"]
# vi sh08.sh
#!/bin/bash
# Program:
# Program shows the effect of shift function.
# History:
# 2009/02/17 VBird First release
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
echo "Total parameter number is ==> $#"
echo "Your whole parameter is ==> '$@'"
shift # 进行第一次『一个变量的 shift 』
echo "Total parameter number is ==> $#"
echo "Your whole parameter is ==> '$@'"
shift 3 # 进行第二次『三个变量的 shift 』
echo "Total parameter number is ==> $#"
echo "Your whole parameter is ==> '$@'"
[/code]
这玩意的运行成果如下:
[code="linux"]
# sh sh08.sh one two three four five six <==给予六个参数
Total parameter number is ==> 6 <==最原始的参数变量情况
Your whole parameter is ==> 'one two three four five six'
Total parameter number is ==> 5 <==第一次偏移,看底下发现第一个 one 不见了
Your whole parameter is ==> 'two three four five six'
Total parameter number is ==> 2 <==第二次偏移掉三个,two three four 不见了
Your whole parameter is ==> 'five six'
[/code]
光看结果你就可以知道啦,[color=red]那个 shift 会移动变量,而且 shift 后面可以接数字,代表拿掉最前面的几个参数的意思。[/color] 上面的运行结果中,第一次进行 shift 后他的显示情况是『 [color=red]one[/color] two three four five six』,所以就剩下五个啦!第二次直接拿掉三个,就变成『 [color=red]two three four[/color] five six 』啦! 这样这个案例可以了解了吗?理解了 shift 的功能了吗?
上面这8个例子都很简单吧?几乎都是利用 bash 的相关功能而已~ 不难啦~底下我们就要使用条件判断式来进行一些分别功能的配置了,好好瞧一瞧先~
转自:[url]http://vbird.dic.ksu.edu.tw/linux_basic/0340bashshell-scripts_3.php[/url]
[size=large][b]利用 test 命令的测试功能[/b][/size]
当我要检测系统上面某些文件或者是相关的属性时,利用 test 这个命令来工作真是好用得不得了, 举例来说,我要检查 /dmtsai 是否存在时,使用:
[code="linux"]
# test -e /dmtsai
[/code]
运行结果并不会显示任何信息,但最后我们可以透过 $? 或 && 及 || 来展现整个结果呢! 例如我们在将上面的例子改写成这样:
[code="linux"]
# test -e /dmtsai && echo "exist" || echo "Not exist"
Not exist <==结果显示不存在啊!
[/code]
最终的结果可以告知我们是『exist』还是『Not exist』呢!那我知道[color=red] -e [/color]是测试一个『东西』在不在, 如果还想要测试一下该档名是啥玩意儿时,还有哪些标志可以来判断的呢?呵呵!有底下这些东西喔!
测试的标志 代表意义
[color=red]1. 关於某个档名的『文件类型』判断,如 test -e filename 表示存在否[/color]
-e 该『档名』是否存在?(常用)
[color=blue]-f 该『档名』是否存在且为文件(file)?(常用)[/color]
[color=blue]-d 该『档名』是否存在且为目录(directory)?(常用)[/color]
-b 该『档名』是否存在且为一个 block device 装置?
-c 该『档名』是否存在且为一个 character device 装置?
-S 该『档名』是否存在且为一个 Socket 文件?
-p 该『档名』是否存在且为一个 FIFO (pipe) 文件?
-L 该『档名』是否存在且为一个连结档?
[color=red]2. 关於文件的权限侦测,如 test -r filename 表示可读否 (但 root 权限常有例外)[/color]
-r 侦测该档名是否存在且具有『可读』的权限?
-w 侦测该档名是否存在且具有『可写』的权限?
-x 侦测该档名是否存在且具有『可运行』的权限?
-u 侦测该档名是否存在且具有『SUID』的属性?
-g 侦测该档名是否存在且具有『SGID』的属性?
-k 侦测该档名是否存在且具有『Sticky bit』的属性?
-s 侦测该档名是否存在且为『非空白文件』?
[color=red]3. 两个文件之间的比较,如: test file1 -nt file2[/color]
-nt (newer than)判断 file1 是否比 file2 新
-ot (older than)判断 file1 是否比 file2 旧
-ef 判断 file1 与 file2 是否为同一文件,可用在判断 hard link 的判定上。 主要意义在判定,两个文件是否均指向同一个 inode 哩!
[color=red]4. 关於两个整数之间的判定,例如 test n1 -eq n2[/color]
-eq 两数值相等 (equal)
-ne 两数值不等 (not equal)
[color=red]-gt n1 大於 n2 (greater than)[/color]
-lt n1 小於 n2 (less than)
-ge n1 大於等於 n2 (greater than or equal)
-le n1 小於等於 n2 (less than or equal)
5. 判定字串的数据
test -z string 判定字串是否为 0 ?若 string 为空字串,则为 true
test -n string 判定字串是否非为 0 ?若 string 为空字串,则为 false。
注: -n 亦可省略
test str1 = str2 判定 str1 是否等於 str2 ,若相等,则回传 true
test str1 != str2 判定 str1 是否不等於 str2 ,若相等,则回传 false
[color=red]6. 多重条件判定,例如: test -r filename -a -x filename[/color]
-a (and)两状况同时成立!例如 test -r file -a -x file,则 file 同时具有 r 与 x 权限时,才回传 true。
-o (or)两状况任何一个成立!例如 test -r file -o -x file,则 file 具有 r 或 x 权限时,就可回传 true。
! 反相状态,如 test ! -x file ,当 file 不具有 x 时,回传 true
OK!现在我们就利用 test 来帮我们写几个简单的例子。首先,判断一下,让使用者输入一个档名,我们判断:
这个文件是否存在,若不存在则给予一个『Filename does not exist』的信息,并中断程序;
若这个文件存在,则判断他是个文件或目录,结果输出『Filename is regular file』或 『Filename is directory』
判断一下,运行者的身份对这个文件或目录所拥有的权限,并输出权限数据!
你可以先自行创作看看,然后再跟底下的结果讨论讨论。注意利用 test 与 && 还有 || 等标志!
[code="linux"]
# vi sh05.sh
#!/bin/bash
# Program:
# User input a filename, program will check the flowing:
# 1.) exist? 2.) file/directory? 3.) file permissions
# History:
# 2005/08/25 VBird First release
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
# 1. 让使用者输入档名,并且判断使用者是否真的有输入字串?
echo -e "Please input a filename, I will check the filename's type and \
permission. \n\n"
read -p "Input a filename : " filename
test -z $filename && echo "You MUST input a filename." && exit 0
# 2. 判断文件是否存在?若不存在则显示信息并结束脚本
test ! -e $filename && echo "The filename '$filename' DO NOT exist" && exit 0
# 3. 开始判断文件类型与属性
test -f $filename && filetype="regulare file"
test -d $filename && filetype="directory"
test -r $filename && perm="readable"
test -w $filename && perm="$perm writable"
test -x $filename && perm="$perm executable"
# 4. 开始输出资讯!
echo "The filename: $filename is a $filetype"
echo "And the permissions are : $perm"
[/code]
如果你运行这个脚本后,他会依据你输入的档名来进行检查喔![color=red]先看是否存在,再看为文件或目录类型,最后判断权限。[/color] 但是你必须要注意的是,由於 root 在很多权限的限制上面都是无效的,所以使用 root 运行这个脚本时, 常常会发现与 ls -l 观察到的结果并不相同!所以,建议使用一般使用者来运行这个脚本试看看。 不过你必须要使用 root 的身份先将这个脚本搬移给使用者就是了,不然一般使用者无法进入 /root 目录的。 很有趣的例子吧!你可以自行再以其他的案例来撰写一下可用的功能呢!
[size=large][b]利用判断符号 [ ][/b][/size]
除了我们很喜欢使用的 test 之外,[color=red]其实,我们还可以利用判断符号『 [ ] 』(就是中括号啦) 来进行数据的判断[/color]呢! 举例来说,如果我想要知道 $HOME 这个变量是否为空的,可以这样做:
[code="linux"]
# [ -z "$HOME" ] ; echo $?
[/code]
使用中括号必须要特别注意,因为中括号用在很多地方,包括万用字节与正规表示法等等,所以如果要在 bash 的语法当中使用中括号作为 shell 的判断式时,必须要注意中括号的两端需要有空白字节来分隔喔! 假设我空白键使用『□』符号来表示,那么,在这些地方你都需要有空白键:
[ "$HOME" == "$MAIL" ]
[□"$HOME"□==□"$MAIL"□]
↑ ↑ ↑ ↑
[color=red]上面的例子在说明,两个字串 $HOME 与 $MAIL 是否相同的意思,相当於 test $HOME = $MAIL 的意思啦![/color] 而如果没有空白分隔,[color=red]例如 [$HOME==$MAIL] 时,我们的 bash 就会显示错误信息了![/color]这可要很注意啊! 所以说,你最好要注意:
[color=red]A 在中括号 [] 内的每个组件都需要有空白键来分隔;[/color]
[color=blue]B 在中括号内的变量,最好都以双引号括号起来;[/color]
[color=blue]C 在中括号内的常数,最好都以单或双引号括号起来。[/color]
为什么要这么麻烦啊?直接举例来说,假如我配置了 name="VBird Tsai" ,然后这样判定:
[code="linux"]
# name="VBird Tsai"
# [ $name == "VBird" ]
bash: [: too many arguments
[/code]
见鬼了!怎么会发生错误啊?bash 还跟我说错误是由於『太多参数 (arguments)』所致! 为什么呢?[color=red]因为 $name 如果没有使用双引号刮起来,那么上面的判定式会变成:[/color]
[ VBird Tsai == "VBird" ]
上面肯定不对嘛!因为一个判断式仅能有两个数据的比对,上面 VBird 与 Tsai 还有 "VBird" 就有三个数据! 这不是我们要的!我们要的应该是底下这个样子:
[ "VBird Tsai" == "VBird" ]
这可是差很多的喔!另外,[color=red]中括号的使用方法与 test 几乎一模一样啊[/color]~ [color=red]只是中括号比较常用在条件判断式 if ..... then ..... fi 的情况中就是了。[/color] 好,那我们也使用中括号的判断来做一个小案例好了,案例配置如下:
当运行一个程序的时候,这个程序会让使用者选择 Y 或 N ,
如果使用者输入 Y 或 y 时,就显示『 OK, continue 』
如果使用者输入 n 或 N 时,就显示『 Oh, interrupt !』
如果不是 Y/y/N/n 之内的其他字节,就显示『 I don't know what your choice is 』
利用中括号、 && 与 || 来继续吧!
[code="linux"]
# vi sh06.sh
#!/bin/bash
# Program:
# This program shows the user's choice
# History:
# 2005/08/25 VBird First release
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
read -p "Please input (Y/N): " yn
[ "$yn" == "Y" -o "$yn" == "y" ] && echo "OK, continue" && exit 0
[ "$yn" == "N" -o "$yn" == "n" ] && echo "Oh, interrupt!" && exit 0
echo "I don't know what your choice is" && exit 0
[/code]
由於输入正确 (Yes) 的方法有大小写之分,不论输入大写 Y 或小写 y 都是可以的,此时判断式内就得要有两个判断才行! 由於是任何一个成立即可 (大小或小写的 y) ,所以这里使用 [color=red]-o (或)[/color] 连结两个判断喔! 很有趣吧!利用这个字串判别的方法,我们就可以很轻松的将使用者想要进行的工作分门别类呢! 接下来,我们再来谈一些其他有的没有的东西吧!
[size=large][b]Shell script 的默认变量($0, $1...)[/b][/size]
我们知道命令可以带有选项与参数,例如 ls -la 可以察看包含隐藏档的所有属性与权限。那么 shell script [color=red]能不能在脚本档名后面带有参数呢?[/color]很有趣喔!举例来说,如果你想要重新启动系统登录档的功能,可以这样做:
[code="linux"]
# file /etc/init.d/syslog
/etc/init.d/syslog: Bourne-Again shell script text executable
# 使用 file 来查询后,系统告知这个文件是个 bash 的可运行 script 喔!
# /etc/init.d/syslog restart[/code]
restart 是重新启动的意思,上面的命令可以『重新启动 /etc/init.d/syslog 这支程序』的意思! 唔!那么如果你在 /etc/init.d/syslog 后面加上 stop 呢?没错!就可以直接关闭该服务了!这么神奇啊? 没错啊!如果你要依据程序的运行给予一些变量去进行不同的任务时,本章一开始是使用 read 的功能!但 read 功能的问题是你得要手动由键盘输入一些判断式。如果透过命令后面接参数, 那么一个命令就能够处理完毕而不需要手动再次输入一些变量行为!这样下达命令会比较简单方便啦!
script 是怎么达成这个功能的呢?其实 script 针对参数已经有配置好一些变量名称了!对应如下:
/path/to/scriptname opt1 opt2 opt3 opt4
$0 $1 $2 $3 $4
这样够清楚了吧?[color=red]运行的脚本档名为 $0 这个变量,第一个接的参数就是 $1 啊[/color]~ 所以,只要我们在 script 里面善用 $1 的话,就可以很简单的立即下达某些命令功能了!除了这些数字的变量之外, 我们还有一些较为特殊的变量可以在 script 内使用来呼叫这些参数喔!
[color=red]$# :代表后接的参数『个数』,以上表为例这里显示为『 4 』[/color];
[color=red]$@ :代表『 "$1" "$2" "$3" "$4" 』之意,每个变量是独立的(用双引号括起来);[/color]
[color=blue]$* :代表『 "$1c$2c$3c$4" 』,其中 c 为分隔字节,默认为空白键, 所以本例中代表『 "$1 $2 $3 $4" 』之意。[/color]
那个 $@ 与 $* 基本上还是有所不同啦!不过,一般使用情况下可以直接记忆 $@ 即可! 好了,来做个例子吧~假设我要运行一个可以携带参数的 script ,运行该脚本后萤幕会显示如下的数据:
程序的档名为何?
共有几个参数?
若参数的个数小於 2 则告知使用者参数数量太少
全部的参数内容为何?
第一个参数为何?
第二个参数为何
[code="linux"]
# vi sh07.sh
#!/bin/bash
# Program:
# Program shows the script name, parameters...
# History:
# 2009/02/17 VBird First release
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
echo "The script name is ==> $0"
echo "Total parameter number is ==> $#"
[ "$#" -lt 2 ] && echo "The number of parameter is less than 2. Stop here." \
&& exit 0
echo "Your whole parameter is ==> '$@'"
echo "The 1st parameter ==> $1"
echo "The 2nd parameter ==> $2"
[/code]
运行结果如下:
[code="linux"]
# sh sh07.sh theone haha quot
The script name is ==> sh07.sh <==档名
Total parameter number is ==> 3 <==果然有三个参数
Your whole parameter is ==> 'theone haha quot' <==参数的内容全部
The 1st parameter ==> theone <==第一个参数
The 2nd parameter ==> haha <==第二个参数
[/code]
[size=small][b]shift:造成参数变量号码偏移[/b][/size]
除此之外,脚本后面所接的变量是否能够进行偏移 (shift) 呢?什么是偏移啊?我们直接以底下的范例来说明好了, 用范例说明比较好解释!我们将 sh07.sh 的内容稍作变化一下,用来显示每次偏移后参数的变化情况:
[code="linux"]
# vi sh08.sh
#!/bin/bash
# Program:
# Program shows the effect of shift function.
# History:
# 2009/02/17 VBird First release
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
echo "Total parameter number is ==> $#"
echo "Your whole parameter is ==> '$@'"
shift # 进行第一次『一个变量的 shift 』
echo "Total parameter number is ==> $#"
echo "Your whole parameter is ==> '$@'"
shift 3 # 进行第二次『三个变量的 shift 』
echo "Total parameter number is ==> $#"
echo "Your whole parameter is ==> '$@'"
[/code]
这玩意的运行成果如下:
[code="linux"]
# sh sh08.sh one two three four five six <==给予六个参数
Total parameter number is ==> 6 <==最原始的参数变量情况
Your whole parameter is ==> 'one two three four five six'
Total parameter number is ==> 5 <==第一次偏移,看底下发现第一个 one 不见了
Your whole parameter is ==> 'two three four five six'
Total parameter number is ==> 2 <==第二次偏移掉三个,two three four 不见了
Your whole parameter is ==> 'five six'
[/code]
光看结果你就可以知道啦,[color=red]那个 shift 会移动变量,而且 shift 后面可以接数字,代表拿掉最前面的几个参数的意思。[/color] 上面的运行结果中,第一次进行 shift 后他的显示情况是『 [color=red]one[/color] two three four five six』,所以就剩下五个啦!第二次直接拿掉三个,就变成『 [color=red]two three four[/color] five six 』啦! 这样这个案例可以了解了吗?理解了 shift 的功能了吗?
上面这8个例子都很简单吧?几乎都是利用 bash 的相关功能而已~ 不难啦~底下我们就要使用条件判断式来进行一些分别功能的配置了,好好瞧一瞧先~
转自:[url]http://vbird.dic.ksu.edu.tw/linux_basic/0340bashshell-scripts_3.php[/url]