鸟哥的 Linux 私房菜Shell Scripts篇(三)
参考:
http://linux.vbird.org/linux_basic/0340bashshell-scripts.php#script_be
http://www.runoob.com/linux/linux-tutorial.html
12.3 善用判断式
在第十章中,我们提到过$?这个变数所代表的意义,此外,也透过&&及|| 来作为前一个指令执行回传值对于后一个指令是否要进行的依据。第十章的讨论中,如果想要判断一个目录是否存在,当时我们使用的是ls这个指令搭配资料流重导向,最后配合$?来决定后续的指令进行与否。但是否有更简单的方式可以来进行『条件判断』呢?有的~那就是『 test 』这个指令。
12.3.1 利用test 指令的测试功能
当我要检测系统上面某些档案或者是相关的属性时,利用test 这个指令来工作真是好用得不得了, 举例来说,我要检查/dmtsai 是否存在时,使用:
[dmtsai@study ~]$ test -e /dmtsai |
执行结果并不会显示任何讯息,但最后我们可以透过$? 或&& 及|| 来展现整个结果呢!例如我们在将上面的例子改写成这样:
[dmtsai@study ~]$ test -e /dmtsai && echo "exist" || echo "Not exist" |
最终的结果可以告知我们是『exist』还是『Not exist』呢!那我知道-e 是测试一个『东西』在不在, 如果还想要测试一下该档名是啥玩意儿时,还有哪些标志可以来判断的呢?呵呵!有底下这些东西喔!
测试的标志 | 代表意义 |
1. 关于某个档名的『档案类型』判断,如test -e filename 表示存在否 | |
-e | 该『档名』是否存在?(常用) |
-f | 该『档名』是否存在且为档案(file)?(常用) |
-d | 该『档名』是否存在且为目录(directory)?(常用) |
-b | 该『档名』是否存在且为一个block device 装置? |
-c | 该『档名』是否存在且为一个character device 装置? |
-S | 该『档名』是否存在且为一个Socket 档案? |
-p | 该『档名』是否存在且为一个FIFO (pipe) 档案? |
-L | 该『档名』是否存在且为一个连结档? |
2. 关于档案的权限侦测,如test -r filename 表示可读否(但root 权限常有例外) | |
-r | 侦测该档名是否存在且具有『可读』的权限? |
-w | 侦测该档名是否存在且具有『可写』的权限? |
-x | 侦测该档名是否存在且具有『可执行』的权限? |
-u | 侦测该档名是否存在且具有『SUID』的属性? |
-g | 侦测该档名是否存在且具有『SGID』的属性? |
-k | 侦测该档名是否存在且具有『Sticky bit』的属性? |
-s | 侦测该档名是否存在且为『非空白档案』? |
3. 两个档案之间的比较,如: test file1 -nt file2 | |
-nt | (newer than)判断file1 是否比file2 新 |
-ot | (older than)判断file1 是否比file2 旧 |
-ef | 判断file1 与file2 是否为同一档案,可用在判断hard link 的判定上。主要意义在判定,两个档案是否均指向同一个inode 哩! |
4. 关于两个整数之间的判定,例如test n1 -eq n2 | |
-eq | 两数值相等(equal) |
-ne | 两数值不等(not equal) |
-gt | n1 大于n2 (greater than) |
-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 |
6. 多重条件判定,例如: test -r filename -a -x filename | |
-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 与&& 还有|| 等标志!
[dmtsai@study bin]$ vim file_perm.sh |
如果你执行这个脚本后,他会依据你输入的档名来进行检查喔!先看是否存在,再看为档案或目录类型,最后判断权限。但是你必须要注意的是,由于root在很多权限的限制上面都是无效的,所以使用root执行这个脚本时,常常会发现与ls -l观察到的结果并不相同!所以,建议使用一般使用者来执行这个脚本试看看。\
除了我们很喜欢使用的test 之外,其实,我们还可以利用判断符号『 [ ] 』(就是中括号啦) 来进行资料的判断呢!举例来说,如果我想要知道${HOME} 这个变数是否为空的,可以这样做:
[dmtsai@study ~]$ [ -z "${HOME}" ] ; echo $? |
使用中括号必须要特别注意,因为中括号用在很多地方,包括万用字元与正规表示法等等,所以如果要在bash的语法当中使用中括号作为shell的判断式时,必须要注意中括号的两端需要有空白字元来分隔喔!假设我空白键使用『□』符号来表示,那么,在这些地方你都需要有空白键:
[ "$HOME" == "$MAIL" ] |
Tips你会发现鸟哥在上面的判断式当中使用了两个等号『 == 』。其实在bash 当中使用一个等号与两个等号的结果是一样的!不过在一般惯用程式的写法中,一个等号代表『变数的设定』,两个等号则是代表『逻辑判断(是与否之意)』。由于我们在中括号内重点在于『判断』而非『设定变数』,因此鸟哥建议您还是使用两个等号较佳!
上面的例子在说明,两个字串${HOME} 与${MAIL} 是否相同的意思,相当于test ${HOME} == ${MAIL} 的意思啦!而如果没有空白分隔,例如[${HOME}==${MAIL}] 时,我们的bash 就会显示错误讯息了!这可要很注意啊!所以说,你最好要注意:
- 在中括号[] 内的每个元件都需要有空白键来分隔;
- 在中括号内的变数,最好都以双引号括号起来;
- 在中括号内的常数,最好都以单或双引号括号起来。
为什么要这么麻烦啊?直接举例来说,假如我设定了name="VBird Tsai" ,然后这样判定:
[dmtsai@study ~]$ name="VBird Tsai" |
见鬼了!怎么会发生错误啊?bash 还跟我说错误是由于『太多参数(arguments)』所致!为什么呢?因为${name} 如果没有使用双引号刮起来,那么上面的判定式会变成:
[ VBird Tsai == "VBird" ]
上面肯定不对嘛!因为一个判断式仅能有两个资料的比对,上面VBird 与Tsai 还有"VBird" 就有三个资料!这不是我们要的!我们要的应该是底下这个样子:
[ "VBird Tsai" == "VBird" ]
这可是差很多的喔!另外,中括号的使用方法与test几乎一模一样啊~只是中括号比较常用在条件判断式if ..... then ..... fi的情况中就是了。好,那我们也使用中括号的判断来做一个小案例好了,案例设定如下:
- 当执行一个程式的时候,这个程式会让使用者选择Y 或N ,
- 如果使用者输入Y 或y 时,就显示『 OK, continue 』
- 如果使用者输入n 或N 时,就显示『 Oh, interrupt !』
- 如果不是Y/y/N/n 之内的其他字元,就显示『 I don't know what your choice is 』
利用中括号、 && 与|| 来继续吧!
[dmtsai@study bin]$ vim ans_yn.sh |
由于输入正确(Yes) 的方法有大小写之分,不论输入大写Y 或小写y 都是可以的,此时判断式内就得要有两个判断才行!由于是任何一个成立即可(大写或小写的y) ,所以这里使用-o (或) 连结两个判断喔!很有趣吧!利用这个字串判别的方法,我们就可以很轻松的将使用者想要进行的工作分门别类呢!接下来,我们再来谈一些其他有的没有的东西吧!
12.3.3 Shell script 的预设变数($0, $1...)
我们知道指令可以带有选项与参数,例如ls -la 可以察看包含隐藏档的所有属性与权限。那么shell script 能不能在脚本档名后面带有参数呢?很有趣喔!举例来说,如果你想要重新启动系统的网路,可以这样做:
[dmtsai@study ~]$ file /etc/init.d/network |
restart是重新启动的意思,上面的指令可以『重新启动/etc/init.d/network这支程式』的意思!唔!那么如果你在/etc/init.d/network后面加上stop呢?没错!就可以直接关闭该服务了!这么神奇啊?没错啊!如果你要依据程式的执行给予一些变数去进行不同的任务时,本章一开始是使用read 的功能!但read功能的问题是你得要手动由键盘输入一些判断式。如果透过指令后面接参数,那么一个指令就能够处理完毕而不需要手动再次输入一些变数行为!这样下达指令会比较简单方便啦!
script 是怎么达成这个功能的呢?其实script 针对参数已经有设定好一些变数名称了!对应如下:
/path/to/scriptname opt1 opt2 opt3 opt4 |
这样够清楚了吧?执行的脚本档名为$0 这个变数,第一个接的参数就是$1 啊~ 所以,只要我们在script 里面善用$1 的话,就可以很简单的立即下达某些指令功能了!除了这些数字的变数之外, 我们还有一些较为特殊的变数可以在script 内使用来呼叫这些参数喔!
- $# :代表后接的参数『个数』,以上表为例这里显示为『 4 』;
- "$@" :代表『 "$1" "$2" "$3" "$4" 』之意,每个变数是独立的(用双引号括起来);
- "$*" :代表『 "$1 c $2 c $3 c $4" 』,其中c为分隔字元,预设为空白键,所以本例中代表『 "$1 $2 $3 $4" 』之意。
那个"$@" 与"$*" 基本上还是有所不同啦!不过,一般使用情况下可以直接记忆"$@" 即可!好了,来做个例子吧~假设我要执行一个可以携带参数的script ,执行该脚本后萤幕会显示如下的资料:
Tips有点怪异的是, $@ 与"$@" 的结果并不一样喔!当你输入的参数内带有双引号(") 时,建议还是得要使用"$@" 来带入脚本中, 否则双引号会被取消,这样执行结果的差异会相当大喔!尤其是像『 ./script one "a to b" 』这种仅有两个参数,但是参数内还有空白字元的, 最容易出现莫名的问题喔!
- 程式的档名为何?
- 共有几个参数?
- 若参数的个数小于2 则告知使用者参数数量太少
- 全部的参数内容为何?
- 第一个参数为何?
- 第二个参数为何
[dmtsai@study bin]$ vim how_paras.sh |
执行结果如下:
[dmtsai@study bin]$ sh how_paras.sh theone haha quot |
- shift:造成参数变数号码偏移
除此之外,脚本后面所接的变数是否能够进行偏移(shift) 呢?什么是偏移啊?我们直接以底下的范例来说明好了, 用范例说明比较好解释!我们将how_paras.sh 的内容稍作变化一下,用来显示每次偏移后参数的变化情况:
[dmtsai@study bin]$ vim shift_paras.sh |
这玩意的执行成果如下:
[dmtsai@study bin]$ sh shift_paras.sh one two three four five six <==给予六个参数 |
光看结果你就可以知道啦,那个shift会移动变数,而且shift后面可以接数字,代表拿掉最前面的几个参数的意思。上面的执行结果中,第一次进行shift后他的显示情况是『one two three four five six』,所以就剩下五个啦!第二次直接拿掉三个,就变成『 two three four five six 』啦!这样这个案例可以了解了吗?理解了shift的功能了吗?
上面这几个例子都很简单吧?几乎都是利用bash 的相关功能而已~ 不难啦~底下我们就要使用条件判断式来进行一些分别功能的设定了,好好瞧一瞧先~
鸟哥的 Linux 私房菜Shell Scripts篇(三)的更多相关文章
- 鸟哥的 Linux 私房菜Shell Scripts篇(一)
参考: http://linux.vbird.org/linux_basic/0340bashshell-scripts.php#script_be http://www.runoob.com/lin ...
- 鸟哥的 Linux 私房菜Shell Scripts篇(四)
12.4 条件判断式 只要讲到『程式』的话,那么条件判断式,亦即是『 if then 』这种判别式肯定一定要学习的!因为很多时候,我们都必须要依据某些资料来判断程式该如何进行.举例来说,我们在上头的a ...
- 鸟哥的 Linux 私房菜Shell Scripts篇(二)
参考: http://linux.vbird.org/linux_basic/0340bashshell-scripts.php#script_be http://www.runoob.com/lin ...
- 拒绝从入门到放弃_《鸟哥的 Linux 私房菜 — 基础学习篇(第三版)》必读目录
目录 目录 前言 关于这本书 必看知识点 最后 前言 相信部分刚进入这个行业的新同学会对一个问题感到疑惑,为什么从培训学校出来的学员不被欢迎? 这里记录下一些我个人的看法(博主也曾有面试新员工的经历) ...
- 每周一书-《鸟哥的Linux私房菜基础学习篇(第四版)》台湾原版,你想要吗?
首先说明,本周活动有效时间为2016年10月19日到2016年10月31日. 目在介绍这本书之前,首先要感谢QQ号为:1084830483(路在远方),来自哈尔滨工程大学的同学赠送给玄魂工作室的 ...
- 【Linux】鸟哥的Linux私房菜基础学习篇整理(一)
最近,一直在写PPC的模拟器和汇编器,也在做设计.所以重新看了看<鸟哥的Linux私房菜>,还是有好多命令不太熟悉.就打算写几篇blog记下来. 1. nl [-bnw] filename ...
- 《鸟哥的Linux私房菜-基础学习篇(第三版)》(三)
第2章 Linxu怎样学习 1. Linux当前的应用角色 当前的Linux常见的应用可略分为企业应用和个人应用双方面. 首先谈了企业环境的利用. 1)网络server. 2)关键任务 ...
- 鸟哥的Linux私房菜 基础学习篇读书笔记(9):Linux磁盘与文件系统管理(2)
上一篇文章主要从理论上分析了Linux的Ext2文件系统.这一篇主要解说怎样查看Linux的文件系统的容量以及解说Linux文件系统中的连接文件. 能够通过df和du命令来查看磁盘与文件夹的容量.df ...
- 《鸟哥的Linux私房菜-基础学习篇(第三版)》(四)
第3章 主机规划与磁盘分区 1. Linux与硬件的搭配 首先谈了认识计算机的硬件配置. 然后谈了选择与Linux搭配的主机配置. 在Linuxserver中,内存的重要性 ...
随机推荐
- 「Java基本功」一文读懂Java内部类的用法和原理
内部类初探 一.什么是内部类? 内部类是指在一个外部类的内部再定义一个类.内部类作为外部类的一个成员,并且依附于外部类而存在的.内部类可为静态,可用protected和private修饰(而外部类只能 ...
- leetcode — integer-to-roman
/** * Source : https://oj.leetcode.com/problems/integer-to-roman/ * * Created by lverpeng on 2017/7/ ...
- Ubuntu中root的默认密码
原文地址:http://www.cnblogs.com/xuyingying/archive/2008/10/16/1312584.html 安装完Ubuntu后忽然意识到没有设 置root密码,不知 ...
- 进程间通信IPC-信号
1,signal-ANSI C信号处理 #include <signal.h> typedef void (*sighandler_t)(int); sighandler_t signal ...
- 使用go语言编写IOS和Android程序
go语言目前已可以用来开发android和ios手机app.相关资料: 1.IOS https://groups.google.com/forum/?utm_medium=email&utm_ ...
- mybatis教程之原理剖析
MyBatis是目前非常流行的ORM框架,功能很强大,然而其实现却比较简单.优雅.本文通过代理的方式来看下其实现 方式一:传统API方式 @Test public void add() throws ...
- [PHP] 数据结构-单链表头插法PHP实现
1.创建头结点 2.创建新结点 3.新结点next指向头结点next 4.头结点next指向新结点 <?php class Node{ public $data; public $next; } ...
- 【Java并发编程】11、volatile的使用及其原理
一.volatile的作用 在<Java并发编程:核心理论>一文中,我们已经提到过可见性.有序性及原子性问题,通常情况下我们可以通过Synchronized关键字来解决这些个问题,不过如果 ...
- 乐字节-Java8新特性之Date API
上一篇文章,小乐给大家带来了Java8新特性之Optional,接下来本文将会给大家介绍Java8新特性之Date API 前言: Java 8通过发布新的Date-Time API来进一步加强对日期 ...
- 微信小程序日历课表
最近项目中使用到了日历,在网上找了一些参考,自己改改,先看效果图 wxml <view class="date"> <image class="dire ...