--------------------------------------------------------------------------------利用 function 功能什么是『函数 (function)』功能啊?简单的说,其实, 函数可以在 shell script 当中做出一个类似自订执行指令的东西,最大的功能是, 可以简化我们很多的程序代码~举例来说,上面的 sh11.sh 当中,每个输入结果 one, two, three 其实输出的内容都一样啊~那么我就可以使用 function 来简化了! function 的语法是这样的:function fname() { 程序段}那个 fname 就是我们的自订的执行指令名称~而程序段就是我们要他执行的内容了。 要注意的是,在 shell script 当中, function 的设定一定要在程序的最前面, 这样才能够在执行时被找到可用的程序段喔!好~我们将 sh11.sh 改写一下:[root@linux scripts]# vi sh11-2.sh#!/bin/bash# Program:# Let user input one, two, three and show in screen.# History:# 2005/08/29 VBird First releasePATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/binexport PATHfunction printit(){ echo -n "Your choice is "}echo "This program will print your selection !"case $1 in "one") printit; echo $1 | tr 'a-z' 'A-Z' ;; "two") printit; echo $1 | tr 'a-z' 'A-Z' ;; "three") printit; echo $1 | tr 'a-z' 'A-Z' ;; *) echo "Usage {one|two|three}" ;;esac以上面的例子来说,我做了一个函数名称为 printif ,所以,当我在后续的程序段里面, 只要执行 printit 的话,就表示我的 shell script 要去执行『 function printit .... 』 里面的那几个程序段落啰! 当然啰,上面这个例子举得太简单了,所以您不会觉得 function 有什么好厉害的, 不过,如果某些程序代码一再地在 script 当中重复时,这个 function 可就重要的多啰~ 不但可以简化程序代码,而且可以做成类似『模块』的玩意儿,真的很棒啦!另外, function 也是拥有内建变量的~他的内建变量与 shell script 很类似, 函数名称代表示 $0 ,而后续接的变量也是以 $1, $2... 来取代的~ 这里很容易搞错喔~因为『 function fname() { 程序段 } 』内的 $0, $1... 等等与 shell script 的 $0 是不同的。以上面 sh11-2.sh 来说,假如我下达:『 sh sh11-2.sh one 』 这表示在 shell script 内的 $1 为 "one" 这个字符串。但是在 printit() 内的 $1 则与这个 one 无关。 我们将上面的例子再次的改写一下,让您更清楚![root@linux scripts]# vi sh11-3.sh#!/bin/bash# Program:# Let user input one, two, three and show in screen.# History:# 2005/08/29 VBird First releasePATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/binexport PATHfunction printit(){ echo "Your choice is $1"}echo "This program will print your selection !"case $1 in "one") printit 1 ;; "two") printit 2 ;; "three") printit 3 ;; *) echo "Usage {one|two|three}" ;;esac在上面的例子当中,如果您输入『 sh sh11-3.sh one 』就会出现『 Your choice is 1 』的字样~ 为什么是 1 呢?因为在程序段落当中,我们是写了『 printit 1 』那个 1 就会成为 function 当中的 $1 喔~ 这样是否理解呢? function 本身其实比较困难一点,如果您还想要进行其它的撰写的话。 不过,我们仅是想要更加了解 shell script 而已,所以,这里看看即可~了解原理就好啰~ ^_^ --------------------------------------------------------------------------------循环 (loop)除了 if...then...fi 这种条件判断式之外,循环可能是程序当中最重要的一环了~ 循环可以不断的执行某个程序段落,直到使用者设定的条件达成为止。 所以,重点是那个『条件的达成』是什么。底下我们就来谈一谈:--------------------------------------------------------------------------------while do done, until do done一般来说,循环最常见的就是底下这两种状态了:while [ condition ]do 程序段落done这种方式中, while 是『当....时』,所以,这种方式说的是『当 condition 条件成立时,就进行循环,直到 condition 的条件不成立才停止』的意思。until [ condition ]do 程序段落done这种方式恰恰与 while 相反,它说的是『当 condition 条件成立时,就终止循环, 否则就持续进行循环的程序段。』是否刚好相反啊~我们以 while 来做个简单的练习好了。 假设我要让使用者输入 yes 或者是 YES 才结束程序的执行,否则就一直进行告知使用者输入字符串。[root@linux scripts]# vi sh12.sh#!/bin/bash# Program:# Use loop to try find your input.# History:# 2005/08/29 VBird First releasePATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/binexport PATHwhile [ "$yn" != "yes" ] && [ "$yn" != "YES" ]do read -p "Please input yes/YES to stop this program: " yndone上面这个例题的说明是『当 $yn 这个变量不是 "yes" 且 $yn 也不是 "YES" 时,才进行循环内的程序。』 而如果 $yn 是 "yes" 或 "YES" 时,就会离开循环啰~那如果使用 until 呢?呵呵有趣啰~ 他的条件会变成这样:[root@linux scripts]# vi sh12-2.sh#!/bin/bash# Program:# Use loop to try find your input.# History:# 2005/08/29 VBird First releasePATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/binexport PATHuntil [ "$yn" == "yes" ] || [ "$yn" == "YES" ]do read -p "Please input yes/YES to stop this program: " yndone仔细比对一下这两个东西有啥不同喔! ^_^再来,如果我想要计算 1+2+3+....+100 这个数据呢? 利用循环啊~他是这样的:[root@linux scripts]# vi sh13.sh#!/bin/bash# Program:# Try to use loop to calculate the result "1+2+3...+100"# History:# 2005/08/29 VBird First releasePATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/binexport PATHs=0i=0while [ "$i" != "100" ]do i=$(($i+1)) s=$(($s+$i))doneecho "The result of '1+2+3+...+100' is ==>; $s"嘿嘿!当您执行了『 sh sh13.sh 』之后,就可以得到 5050 这个数据才对啊!这样瞭呼~ 那么让您自行做一下,如果想要让使用者自行输入一个数字,让程序由 1+2+... 直到您输入的数字为止, 该如何撰写呢?应该很简单吧?!答案可以参考一下习题练习里面的一题喔!--------------------------------------------------------------------------------for...do....done相对于 while, until 的循环方式是必须要『符合某个条件』的状态, for 这种语法,则是『 已经知道要进行几次循环』的状态!他的语法是:for (( 初始值; 限制值; 执行步阶 ))do 程序段done这种语法适合于数值方式的运算当中,在 for 后面的括号内的三串内容意义为:初始值:某个变量在循环当中的起始值,直接以类似 i=1 设定好; 限制值:当变量的值在这个限制值的范围内,就继续进行循环。例如 i<=100; 执行步阶:每作一次循环时,变量的变化量。例如 i=i+1。值得注意的是,在『执行步阶』的设定上,如果每次增加 1 ,则可以使用类似『i++』的方式,亦即是 i 每次循环都会增加一的意思。好,我们以这种方式来进行 1 累加到 100 的循环吧![root@linux scripts]# vi sh14.sh#!/bin/bash# Program:# Try do calculate 1+2+....+100# History:# 2005/08/29 VBird First releasePATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/binexport PATHs=0for (( i=1; i<=100; i=i+1 ))do s=$(($s+$i))doneecho "The result of '1+2+3+...+100' is ==>; $s"一样也是很简单吧!利用这个 for 则可以直接限制循环要进行几次呢!这么好用的东西难道只能在数值方面动作? 当然不是啦~我们还可以利用底下的方式来进行非数字方面的循环运作喔!for $var in con1 con2 con3 ...do 程序段done以上面的例子来说,这个 $var 的变量内容在循环工作时:第一次循环时, $var 的内容为 con1 ; 第二次循环时, $var 的内容为 con2 ; 第三次循环时, $var 的内容为 con3 ; ....我们可以做个简单的练习。假设我有三种动物,分别是 dog, cat, elephant 三种, 我想每一行都输出这样:『There are dogs...』之类的字样,则可以:[root@linux scripts]# vi sh15.sh#!/bin/bash# Program:# Using for .... loop to print 3 animal # History:# 2005/08/29 VBird First releasePATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/binexport PATHfor animal in dog cat elephantdo echo "There are ""$animal""s.... "done很简单是吧! ^_^。好了,那么如果我想要让使用者输入某个目录, 然后我找出某目录内的文件名的权限呢?又该如何是好?呵呵!可以这样做啦~[root@linux scripts]# vi sh16.sh#!/bin/bash# Program:# let user input a directory and find the whole file's permission.# History:# 2005/08/29 VBird First releasePATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/binexport PATH# 1. 先看看这个目录是否存在啊?read -p "Please input a directory: " dirif [ "$dir" == "" ] || [ ! -d "$dir" ]; then echo "The $dir is NOT exist in your system." exit 1fi# 2. 开始测试档案啰~filelist=`ls $dir`for filename in $filelistdo perm="" test -r "$dir/$filename" && perm="$perm readable" test -w "$dir/$filename" && perm="$perm writable" test -x "$dir/$filename" && perm="$perm executable" echo "The file $dir/$filename's permission is $perm "done呵呵!很有趣的例子吧~利用这种方式,您可以很轻易的来处理一些档案的特性呢~ 我们循环就介绍到这里了~其它更多的应用,就得视您的需求来玩啰~。 --------------------------------------------------------------------------------shell script 的追踪与 debugscripts 在执行之前,最怕的就是出现问题了!那么我们如何 debug 呢?有没有办法不需要透过直接执行该 scripts 就可以来判断是否有问题呢!?呵呵! 当然是有的!我们就直接以 bash 的相关参数来进行判断吧![root@linux ~]# sh [-nvx] scripts.sh参数:-n :不要执行 script,仅查询语法的问题;-v :再执行 sccript 前,先将 scripts 的内容输出到屏幕上;-x :将使用到的 script 内容显示到屏幕上,这是很有用的参数!范例:范例一:测试 sh16.sh 有无语法的问题?[root@linux ~]# sh -n sh16.sh # 若语法没有问题,则不会显示任何信息!范例二:将 sh15.sh 的执行过程全部列出来~[root@linux ~]# sh -x sh15.sh + PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:/home/vbird/bin+ export PATH+ for animal in dog cat elephant+ echo 'There are dogs.... 'There are dogs....+ for animal in dog cat elephant+ echo 'There are cats.... 'There are cats....+ for animal in dog cat elephant+ echo 'There are elephants.... 'There are elephants....# 使用 -x 真的是追踪 script 的好方法,他可以将所有有执行的程序段在执行前列出来,# 如果是程序段落,则输出时,最前面会加上 + 字号,表示他是程序代码而已,# 实际的输出则与 standard output 有关啊~如上所示。在上面的范例二当中,我们可以透过这个简单的参数 -x 来达成 debug 的目的,这可是一个不可多得的参数, 通常如果您执行 script 却发生问题时,利用这个 -x 参数,就可以知道问题是发生在哪一行上面了!熟悉 sh 的用法,将可以使您在管理 Linux 的过程中得心应手!至于在 Shell scripts 的学习方法上面,需要『多看、多模仿、并加以修改成自己的样式!』 是最快的学习手段了!网络上有相当多的朋友在开发一些相当有用的 scripts ,若是您可以将对方的 scripts 拿来,并且改成适合自己主机的样子!那么学习的效果会是最快的呢!另外,我们 Linux 系统本来就有很多的启动 script ,如果您想要知道每个 script 所代表的功能是什么? 可以直接以 vi 进入该 script 去查阅一下,通常立刻就知道该 script 的目的了。 举例来说,我们的 Linux 里头有个文件名称为: /etc/init.d/portmap ,这个 script 是干嘛用的? 利用 vi 去查阅最前面的几行字,他出现如下信息:# description: The portmapper manages RPC connections, which are used by # protocols such as NFS and NIS. The portmap server must be # running on machines which act as servers for protocols which # make use of the RPC mechanism.# processname: portmap简单的说,他是被用在 NFS 与 NIS 上面的一个启动 RPC 的 script , 然后我们再利用 http://www.google.com.tw 去搜寻一下 NFS, NIS 与 RPC , 立刻就能够知道这个 script 的功能啰~所以,下次您发现不明的 script 时, 如果是系统提供的,那么利用这个检查的方式,一定可以约略了解的啦! 加油的啰~ ^_^另外,本章所有的范例都可以在 http://linux.vbird.org/linux_basic/0340bashshell-scripts/scripts.tgz 里头找到喔!加油~--------------------------------------------------------------------------------本章习题练习( 要看答案请将鼠标移动到『答:』底下的空白处,按下左键圈选空白处即可察看 ) 请建立一支 script ,当你执行该 script 的时候,该 script 可以显示: 1. 你目前的身份 (用 whoami ) 2. 你目前所在的目录 (用 pwd) #!/bin/bashecho -e "Your name is ==>; `whoami`"echo -e "The current directory is ==>; `pwd`"请自行建立一支程序,该程序可以用来计算『您还有几天可以过生日』啊?? #!/bin/bashread -p "Pleas input your birthday (MMDD, ex>; 0709): " birnow=`date +%m%d`if [ "$bir" == "$now" ]; thenecho "Happy Birthday to you!!!"elif [ "$bir" -gt "$now" ]; thenyear=`date +%Y`total_d=$(($((`date --date="$year$bir" +%s`-`date +%s`))/60/60/24))echo "Your birthday will be $total_d later"elseyear=$((`date +%Y`+1))total_d=$(($((`date --date="$year$bir" +%s`-`date +%s`))/60/60/24))echo "Your birthday will be $total_d later"fi让使用者输入一个数字,程序可以由 1+2+3... 一直累加到使用者输入的数字为止。 #!/bin/bashread -p "Please input an integer number: " numberi=0s=0while [ "$i" != "$number" ]doi=$(($i+1))s=$(($s+$i))doneecho "the result of '1+2+3+...$number' is ==>; $s"撰写一支程序,他的作用是: 1.) 先查看一下 /root/test/logical 这个名称是否存在; 2.) 若不存在,则建立一个档案,使用 touch 来建立,建立完成后离开; 3.) 如果存在的话,判断该名称是否为档案,若为档案则将之删除后建立一个档案,档名为 logical ,之后离开; 4.) 如果存在的话,而且该名称为目录,则移除此目录! #!/bin/bashif [ ! -e logical ]; thentouch logicalecho "Just make a file logical"exit 1elif [ -e logical ] && [ -f logical ]; thenrm logicalmkdir logicalecho "remove file ==>; logical"echo "and make directory logical"exit 1elif [ -e logical ] && [ -d logical ]; thenrm -rf logicalecho "remove directory ==>; logical"exit 1elseecho "Does here have anything?"fi我们知道 /etc/passwd 里面以 : 来分隔,第一栏为账号名称。请写一只程序,可以将 /etc/passwd 的第一栏取出,而且每一栏都以一行字符串『The 1 account is "root" 』来显示,那个 1 表示行数。 #!/bin/bashaccounts=`cat /etc/passwd | cut -d':' -f1`for account in $accountsdodeclare -i i=$i+1echo "The $i account is "$account" "done
SHELL 经典入门材料3
最新推荐文章于 2024-08-29 15:39:07 发布