Shell条件语句

7.1退出状态

Linux程序执行完成,就会向Shell返回一个退出状态码,按照惯例,为0的状态码就表示程序执行成功,非0的表示失败。

7.2变量$?

Shell会将变量$?自动设置为最后一条命令的退出状态。可以通过echo命令打印该变量查看。

[root@centos7_c1 linux]# ls
intro  introo  intros  ison  names  script
[root@centos7_c1 linux]# cp intro introbak
[root@centos7_c1 linux]# echo $?
0
[root@centos7_c1 linux]# cp intro1 intro2

cp: 无法获取"intro1" 的文件状态(stat): 没有那个文件或目录

[root@centos7_c1 linux]# echo $?
1
[root@centos7_c1 linux]# 

下面我们创建一个shell文件,运行查看指定名称的用户是否已登录。
不妨命名该文件为:
on_v1
通过vim编辑内容

[root@centos7_c1 linux]# vim on_v1
[root@centos7_c1 linux]# cat on_v1 

#
#确定用户是否已经登录
#

user="$1"

if who | grep "$user"
then
	echo "$user is logged on"
fi
[root@centos7_c1 linux]# 

接下来测试一下,

[root@centos7_c1 linux]# who
chase    pts/0        2019-07-08 10:55 (172.16.80.1)
root     pts/1        2019-07-08 11:07 (172.16.80.1)
[root@centos7_c1 linux]# ./on_v1 chase

bash: ./on_v1: 权限不够

[root@centos7_c1 linux]# chmod +x on_v1
[root@centos7_c1 linux]# ./on_v1 chase
chase    pts/0        2019-07-08 10:55 (172.16.80.1)
chase is logged on
[root@centos7_c1 linux]# ./on_v1 qiao
[root@centos7_c1 linux]# ./on_v1 cha
chase    pts/0        2019-07-08 10:55 (172.16.80.1)
cha is logged on
[root@centos7_c1 linux]# 

通过以上的测试命令,首先要赋予用户可执行on_v1文件的权限。我们只是想查看指定的用户是否已经登录,但是从shell的输出结果上看,它还给我们输出多了一行这样的:

chase    pts/0        2019-07-08 10:55 (172.16.80.1)

哪怕我们根本就不想输出这行。这是因为grep不仅会在管道中返回退出状态,而且还会将匹配的行写入到标准输出。解决这个问题,我们可以把grep的输出重定向到系统的“垃圾桶”:/dev/null。这是一个特殊的系统文件,任何人都可以读取(立刻会得到一个EOF)或写入。向该文件写入的任何东西都会消失,就像一个巨大的黑洞一样。

who | grep "$user" > /dev/null

这样就可以解决这个问题了。
还有第二个问题,我想眼快的读者已经发现了:

[root@centos7_c1 linux]# ./on_v1 cha
chase    pts/0        2019-07-08 10:55 (172.16.80.1)
cha is logged on

我们只是输入用户cha,但是控制台给我们输出了已经登录的chase用户,这个问题我们就通过正则来解决吧:

"^$user "

前面加^,后面加空格。
通过cat查看修改后的on程序,这次命名为on_v2

[root@centos7_c1 linux]# cat on_v2
#
#确定用户是否已经登录
#

user="$1"

if who | grep "^$user " > /dev/null
then
	echo "$user is logged on"
fi

查看当前登录的用户。

[root@centos7_c1 linux]# who
chase    pts/0        2019-07-08 10:55 (172.16.80.1)
root     pts/1        2019-07-08 11:07 (172.16.80.1)

测试修改后的效果。

[root@centos7_c1 linux]# ./on_v2 chase
chase is logged on
[root@centos7_c1 linux]# ./on_v2 cha
[root@centos7_c1 linux]# 

7.3 test命令

test的一般格式:
test expression
例子:
[root@centos7_c1 linux]# symbol=abc
[root@centos7_c1 linux]# echo KaTeX parse error: Expected 'EOF', got '#' at position 35: …ntos7_c1 linux]#̲ test -z "symbol"
[root@centos7_c1 linux]# echo KaTeX parse error: Expected 'EOF', got '#' at position 28: …ntos7_c1 linux]#̲ test的另一种格式: …symbol" ]
[root@centos7_c1 linux]# echo $?
1
[root@centos7_c1 linux]#
注意:这种格式在[之后和]之前必须要有空格。

字符串操作符:

操作符如果满足一下条件,则返回真(退出状态码为0)
string1 = string2string1等于string2
string1 != string2string1不等于string2
stringstring不为空
-n stringstring不为空(test必须能够识别出作为参数的string)
-z stringstring为空(test必须能够识别出作为参数的string)

整数操作符:

操作符如果满足一下条件,则返回真(退出状态码为0)
int1 -eq int2int1等于int2
int1 -ge int2int1大于或等于int2
int1 -gt int2int1大于int2
int1 -le int2int1小于或等于int2
int1 -lt int2int1小于int2
int1 -ne int2int1不等于int2

文件操作符:

操作符如果满足一下条件,则返回真(退出状态码为0)
-d filefile是一个目录
-e filefile存在
-f filefile是一个普通文件
-r filefile可由进程读取
-s filefile不是空文件
-w filefile可由进程写入
-x filefile可由进程执行
-L filefile是一个符号链接

逻辑否定操作符!
一元逻辑否定操作符!可以放置在任意的test表达式之前,否定该表达式的求值结果。例如:
[ ! -r /usrs/chase/phonebook ]

逻辑“与”操作符-a
操作符-a在两个表达式之间执行逻辑“与”运算,仅当这两个表达式均为真时,才返回真。
[ -f “ m a i l f i l e " − a − r " mailfile" -a -r " mailfile"ar"mailfile” ]

逻辑“或”操作符为-o

括号
由于表达式中符号优先级的关系,有时要借助括号。
例子:
[ “ c o u n t " − g e 0 − a " count" -ge 0 -a " count"ge0a"count” -lt 10 ]
可以改写为:
[ ( “KaTeX parse error: Can't use function '\)' in math mode at position 14: count" -ge 0 \̲)̲ -a \( "count” -lt 10 ) ]

7.4 else

if命令中可以加入else,其一般格式为:

if commandt
then
		command
		command
		...
else
		command
		command
...
fi

例子:

[root@centos7_c1 linux]# cat on_v3
#
#确定用户是否已经登录
#

user="$1"

if who | grep "^$user " > /dev/null
then
	echo "$user is logged on"
else
	echo "$user is not logged on"
fi
[root@centos7_c1 linux]# who
chase    pts/0        2019-07-08 10:55 (172.16.80.1)
root     pts/1        2019-07-08 11:07 (172.16.80.1)
[root@centos7_c1 linux]# ./on_v3 chase
chase is logged on
[root@centos7_c1 linux]# ./on_v3 tom
tom is not logged on
[root@centos7_c1 linux]# 

实际上这个程序输入非一个参数是有问题的:

[root@centos7_c1 linux]# ./on_v3 chase tom
chase is logged on
[root@centos7_c1 linux]# 

优化一下,cat查看优化后的内容

[root@centos7_c1 linux]# cat on_v4

#
#确定用户是否已经登录
#

if [ "$#" -ne 1 ]
then
	echo "Incorrect number of arguments"
	echo "Usage: on user"
else

	user="$1"

	if who | grep "^$user " > /dev/null
	then
		echo "$user is logged on"
	else
		echo "$user is not logged on"
	fi
fi
[root@centos7_c1 linux]# ./on_v4 chase root
Incorrect number of arguments
Usage: on user
[root@centos7_c1 linux]# ./on_v4 chase
chase is logged on
[root@centos7_c1 linux]# 

7.5 exit命令

shell内建的exit命令可以立刻终止shell程序的执行。其一般格式为:

exit n

其中n是你要返回的状态码。如果没有指定,则使用在exit之前最后执行的那条命令的退出状态(其实就是 exit $?)。
举例说明
有从电话薄中删除联系人程序,通过cat查看源码:

[root@centos7_c1 linux]# cat rem_v1 
#
#从电话薄中删除联系人
#

grep -v "$1" phonebook > /tmp/phonebook
mv /tmp/phonebook phonebook

[root@centos7_c1 linux]# 

优化一下,检查参数格式,

[root@centos7_c1 linux]# cat rem_v2
#
#从电话薄中删除联系人
#

if [ "$#" -ne 1 ]
then
	echo "Incorrect number of arguments."
	echo "Usage: rem name"
	exit 1
fi


grep -v "$1" phonebook > /tmp/phonebook
mv /tmp/phonebook phonebook

[root@centos7_c1 linux]# 

7.6 elif

elif的一般格式为:

if command1
then
	command
	command
	...
elif command2
then
	command
	command
	...
else
	command
	command
	...
fi

下面给出一个根据不同时间段问候的案例,

[root@centos7_c1 linux]# cat greetings 
#
#打印欢迎信息
#

#hour=$(date | cut -c12-13)
hour=$(date +%H)

if [ "$hour" -ge 0 -a "$hour" -le 11 ]
then
	echo "Good morning"
elif [ "$hour" -ge 12 -a "$hour" -le 17 ]
then
	echo "Good afternoon"
else
	echo "Good evening"
fi

[root@centos7_c1 linux]# 

执行效果

[root@centos7_c1 linux]# ./greetings 
Good afternoon
[root@centos7_c1 linux]# 

通过elif再优化一下rem程序,查看

[root@centos7_c1 linux]# cat rem_v3
#
#从电话薄中删除联系人
#

if [ "$#" -ne 1 ]
then
	echo "Incorrect number of arguments."
	echo "Usage: rem name"
	exit 1
fi

name=$1

#
#找出匹配条目数量
#

matches=$(grep "$name" phonebook | wc -l)

#
#
#

if [ "$matches" -gt 1 ]
then
	echo "More than one match; please qualify further"
elif [ "$matches" -eq 1 ]
then
	grep -v "$name" phonebook > /tmp/phonebook
	mv /tmp/phonebook phonebook
else
	echo "I couldn't find $name in the phone book"
fi

[root@centos7_c1 linux]# 

7.7 case

case 命令可以将单个值与一组值或表达式进行比较,在有匹配的时候执行一个或多个命令。其一般格式为:
case value in
pattern1) command
command

command;;

pattern2) command
				command
				...
				command;;

pattern3) command
command

command;;
esac

value会连续和pattern1、pattern2…patternn比较,直到找到匹配项。接着,执行所匹配值之后的命令,碰到双分号后停止,双分号在这里起到break语句的作用。如果没找到匹配项,case中的命令一个都不执行。下面给出一个从数字翻译成英语的例子:

[root@centos7_c1 linux]# cat number 
#
#将数字翻译成英语
#

if [ "$#" -ne 1 ]
then
	echo "Uage: number digit"
	exit 1
fi

case "$1"
in
	0) echo zero;;
	1) echo one;;
	2) echo two;;
	3) echo three;;
	4) echo four;;
	5) echo five;;
	6) echo six;;
	7) echo seven;;
	8) echo eight;;
	9) echo nine;;
esac

[root@centos7_c1 linux]# 

特殊的模式匹配字符

调试选项 -x

[root@centos7_c1 linux]# sh -x number 5
+ '[' 1 -ne 1 ']'
+ case "$1" in
+ echo five
five
[root@centos7_c1 linux]# 

7.8 空命令:

什么都不做。

7.9 &&和||

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

春侨

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值