利用 case ..... esac 判断
上个小节提到的『 if .... then .... fi 』对於变量的判断是以『比对』的方式来分辨的, 如果符合状态就进行某些行为,并且透过较多层次 (就是 elif ...) 的方式来进行多个变量的程序码撰写,譬如 sh09.sh 那个小程序,就是用这样的方式来撰写的罗。 好,那么万一我有多个既定的变量内容,例如 sh09.sh 当中,我所需要的变量就是 "hello" 及空字串两个, 那么我只要针对这两个变量来配置状况就好了,对吧?那么可以使用什么方式来设计呢?呵呵~就用 case ... in .... esac 吧~,他的语法如下:
|
要注意的是,这个语法以 case (实际案例之意) 为开头,结尾自然就是将 case 的英文反过来写!就成为 esac 罗! 不会很难背啦!另外,每一个变量内容的程序段最后都需要两个分号 (;;) 来代表该程序段落的结束,这挺重要的喔! 至於为何需要有 * 这个变量内容在最后呢?这是因为,如果使用者不是输入变量内容一或二时, 我们可以告知使用者相关的资讯啊!废话少说,我们拿 sh09.sh 的案例来修改一下,他应该会变成这样喔:
|
在上面这个 sh09-2.sh 的案例当中,如果你输入『 sh sh09-2.sh test 』来运行, 那么萤幕上就会出现『Usage sh09-2.sh {hello}』的字样,告知运行者仅能够使用 hello 喔~ 这样的方式对於需要某些固定字串来运行的变量内容就显的更加的方便呢! 这种方式你真的要熟悉喔!这是因为系统的很多服务的启动 scripts 都是使用这种写法的, 举例来说,我们 Linux 的服务启动放置目录是在 /etc/init.d/ 当中,我已经知道里头有个 syslog 的服务,我想要重新启动这个服务,可以这样做:
/etc/init.d/syslog restart
重点是那个 restart 啦!如果你使用『 less /etc/init.d/syslog 』去查阅一下,就会看到他使用的是 case 语法, 并且会规定某些既定的变量内容,你可以直接下达 /etc/init.d/syslog , 该 script 就会告知你有哪些后续接的变量可以使用罗~方便吧! ^_^
一般来说,使用『 case $变量 in 』这个语法中,当中的那个『 $变量 』大致有两种取得的方式:
直接下达式:例如上面提到的,利用『 script.sh variable 』 的方式来直接给予 $1 这个变量的内容,这也是在 /etc/init.d 目录下大多数程序的设计方式。
互动式:透过 read 这个命令来让使用者输入变量的内容。
这么说或许你的感受性还不高,好,我们直接写个程序来玩玩:让使用者能够输入 one, two, three , 并且将使用者的变量显示到萤幕上,如果不是 one, two, three 时,就告知使用者仅有这三种选择。
|
此时,你可以使用『 sh sh12.sh two 』的方式来下达命令,就可以收到相对应的回应了。 上面使用的是直接下达的方式,而如果使用的是互动式时,那么将上面第 10, 11 行的 "#" 拿掉, 并将 12 行加上注解 (#),就可以让使用者输入参数罗~这样是否很有趣啊?
利用 function 功能
什么是『函数 (function)』功能啊?简单的说,其实, 函数可以在 shell script 当中做出一个类似自订运行命令的东西,最大的功能是, 可以简化我们很多的程序码~举例来说,上面的 sh12.sh 当中,每个输入结果 one, two, three 其实输出的内容都一样啊~那么我就可以使用 function 来简化了! function 的语法是这样的:
|
那个 fname 就是我们的自订的运行命令名称~而程序段就是我们要他运行的内容了。 要注意的是,因为 shell script 的运行方式是由上而下,由左而右, 因此在 shell script 当中的 function 的配置一定要在程序的最前面, 这样才能够在运行时被找到可用的程序段喔!好~我们将 sh12.sh 改写一下,自订一个名为 printit 的函数来使用喔:
|
以上面的例子来说,鸟哥做了一个函数名称为 printit ,所以,当我在后续的程序段里面, 只要运行 printit 的话,就表示我的 shell script 要去运行『 function printit .... 』 里面的那几个程序段落罗!当然罗,上面这个例子举得太简单了,所以你不会觉得 function 有什么好厉害的, 不过,如果某些程序码一再地在 script 当中重复时,这个 function 可就重要的多罗~ 不但可以简化程序码,而且可以做成类似『模块』的玩意儿,真的很棒啦!
function 也是拥有内建变量的~他的内建变量与 shell script 很类似, 函数名称代表示 $0 ,而后续接的变量也是以 $1, $2... 来取代的~ 这里很容易搞错喔~因为『 function fname() { 程序段 } 』内的 $0, $1... 等等与 shell script 的 $0 是不同的。以上面 sh12-2.sh 来说,假如我下达:『 sh sh12-2.sh one 』 这表示在 shell script 内的 $1 为 "one" 这个字串。但是在 printit() 内的 $1 则与这个 one 无关。 我们将上面的例子再次的改写一下,让你更清楚!
|
在上面的例子当中,如果你输入『 sh sh12-3.sh one 』就会出现『 Your choice is 1 』的字样~ 为什么是 1 呢?因为在程序段落当中,我们是写了『 printit 1 』那个 1 就会成为 function 当中的 $1 喔~ 这样是否理解呢?