简介

在bash脚本编程中,条件结构体使用if语句和case语句两种句式。

if语句

单分支if语句

if TEST; then
CMD
fi

TEST:条件判断,多数情况下可使用test命令来实现,返回值为0的话则执行CMD,否则就离开该条件结构体,脚本继续往下执行。

[root@c7-server ~]# cat test.sh
#!/bin/bash
if id zwl &> /dev/null; then
echo "User zwl exists."
fi
[root@c7-server ~]# bash test.sh
User zwl exists.

双分支if语句

if TEST; then
  CMD-TRUE
else
  CMD-FALSE
fi

为真执行CMD-TRUE,为假执行CMD-FALSE。

[root@c7-server ~]# cat test.sh
#!/bin/bash
read -p "Pleas input a user name:" name
if id $name &> /dev/null; then
echo "User $name exists."
else
echo "User $name doesn't exists."
fi
[root@c7-server ~]# bash test.sh
Pleas input a user name:zwl
User zwl exists.
[root@c7-server ~]# bash test.sh
Pleas input a user name:alongdidi
User alongdidi doesn't exists.

多分支if语句

if TEST1; then
CMD1
elif TEST2; then
CMD2
elif TEST3; then
CMD3
...
else
CMD-LAST
fi

当TEST1为真时执行CMD1,否则判断TEST2;当TEST2为真时执行CMD2,否则判断TEST3;以此类推,都不符合条件的话则执行CMD-LAST。

判断文件类型的示例。

#!/bin/bash
read -p "Please input only a absolute file path:" file if [ -z $file ]; then
echo "You must input something."
exit
fi if [ ! -e $file ]; then
echo "No such file $file"
elif [ -d $file ]; then
echo "File $file is a directory."
elif [ -L $file ]; then
echo "File $file is a symbolic."
elif [ -b $file ]; then
echo "File $file is a block special file."
elif [ -c $file ]; then
echo "File $file is a character special file."
elif [ -S $file ]; then
echo "File $file is a socket file."
elif [ -f $file ]; then
echo "File $file is a regular file."
else
echo "File is unrecognized."
fi

执行示例。

[root@c7-server ~]# bash test.sh
Please input only a absolute file path:
You must input something.
[root@c7-server ~]# bash test.sh
Please input only a absolute file path:passwd
No such file passwd
[root@c7-server ~]# bash test.sh
Please input only a absolute file path:/etc/passwd
File /etc/passwd is a regular file
[root@c7-server ~]# bash test.sh
Please input only a absolute file path:/root/
File /root/ is a directory.
[root@c7-server ~]# bash test.sh
Please input only a absolute file path:/etc/rc.local
File /etc/rc.local is a symbolic.

字符链接文件也可以被认为是普通文件(regular),因此建议将普通文件的判定放置在较靠后的位置。

注意:if语句是可以嵌套的。

[root@c7-server ~]# cat test.sh
#!/bin/bash
if [ -e /dev/sda ]; then
if [ -b /dev/sda ]; then
echo "It's a block file."
fi
fi
[root@c7-server ~]# bash test.sh
It's a block file.

其他示例

编写一个脚本,仅可接收一个参数,此参数应是一个用户名称。判断该用户名是否存在,若存在则输出用户的信息,否则就创建该用户并设置默认密码(password)。

#!/bin/bash

if [ $# -ne  ];then
echo "You must input just one argument!"
exit
fi if id $ &> /dev/null; then
id $
else
useradd $
echo "password" | passwd --stdin $ &> /dev/null
fi

编写一个脚本,接收两个数值类参数,并输出其中较大的那个。

#!/bin/bash

if [ $# -ne  ]; then
echo "Please input exact two number arguments."
exit
fi if [ $ -eq $ ]; then
echo "Number $1 and $2 are equal."
elif [ $ -gt $ ]; then
echo "The greater is $1."
else
echo "The greater is $2."
fi

编写一个脚本,接收一个用户名作为参数,并判断其奇偶性。

[root@c7-server ~]# cat even_odd_if.sh
#!/bin/bash if [ $# -ne ]; then
echo "You must input just one argument."
exit
fi var=$[$(id -u $)%]
if [ $var -eq ]; then
echo "The UID of $1 is even."
else
echo "The UID of $1 is odd."
fi

编写一个脚本,接收两个文件名作为参数,返回文件的行数以及判断哪个文件的行数比较多。

#!/bin/bash

if [ $# -ne  ]; then
echo "You must input exat 2 arguments."
exit
fi if [ ! -e $ -o ! -e $ ]; then
echo "File $1 or/and $2 doesn't/don't exist[s]."
exit
fi line1=$(wc -l $ | cut -d " " -f )
line2=$(wc -l $ | cut -d " " -f )
echo "The lines of $1 is $line1"
echo "The lines of $2 is $line2" if [ $line1 -gt $line2 ]; then
echo "$1 has more lines."
elif [ $line1 -lt $line2 ]; then
echo "$2 has more lines."
else
echo "They have same lines."
fi

编写一个脚本,传递一个用户名作为参数给脚本,判断用户的类型。

UID=0:管理员

UID=1~999:系统用户

UID=1000+:普通用户

#!/bin/bash

if [ $# -ne  ]; then
echo "You must input exact one argument."
exit
fi if ! id $ &> /dev/null; then
echo "You must input an existed username."
exit
fi userId=$(id -u $)
if [ $userId -eq ]; then
echo "$1 is a admin user."
elif [ $userId -lt ]; then
echo "$1 is a system user."
else
echo "$1 is a normal user."
fi

编写一个脚本,展示一个菜单供用户选择,菜单告知用户脚本可以显示的系统信息。

#!/bin/bash

cat << EOF
disk) Show disk infomation.
mem) Show memory infomation.
cpu) Show cpu infomation.
*) QUIT!
EOF read -p "Your option is: " option
if [ -z $option ]; then
echo "You input nothing,QUIT!"
exit
elif [ $option == disk ]; then
fdisk -l
elif [ $option == mem ]; then
free -m
elif [ $option == cpu ]; then
lscpu
else
echo "You input a illegal string,QUIT now!"
fi

在后面学习了循环之后,可以加上循环,使得用户在输入错误的情况下,反复让用户输入直到输入正确的选项。

#!/bin/bash

cat << EOF
disk) Show disk infomation.
mem) Show memory infomation.
cpu) Show cpu infomation.
*) Again!
EOF read -p "Your option is: " option while [ "$option" != disk -a "$option" != mem -a "$option" != cpu -o "$option" == "" ]; do
echo "You input a illegal string. Usage {disk|mem|cpu}, case sensitive."
read -p "Your option is: " option
done if [ $option == disk ]; then
fdisk -l
elif [ $option == mem ]; then
free -m
elif [ $option == cpu ]; then
lscpu
fi

这个脚本的难点我觉得在于while循环中的判断应该怎么写,$option是否应该加引号、字符串匹配右边的字符(如disk)是否需要加引号、使用单中括号还是双中括号、使用单引号还是双引号。我也是一遍遍试直到瞎猫碰到死耗子才写出来符合自己需求的bash代码。

具体涉及的难点包括但《Bash脚本编程学习笔记04:测试命令test、状态返回值、位置参数和特殊变量》文章开头说的那些,因此这里无法为大家做到准确的分析。

case语句

像上述脚本中,我们反复对一个变量做字符串等值比较并使用了多分支的if语句。此类情况我们完全可以使用case语句来代替,使其更容易看懂。

其官方语法如下:

case word in
[ [(] pattern [| pattern]…) command-list ;;]…
esac

case会将word和pattern进行匹配,一旦匹配到就执行对应的command-list,并且退出。

pattern基于bash的模式匹配,即glob风格。

pattern至少一个,可以有多个使用“|”分隔。

pattern+command-list成为一个子句(clause),如下。

[(] pattern [| pattern]…) command-list ;;

每个子句,都会以“;;”或者“;&”或者“;;&”结束。基本上只会使用“;;”。

;;:决定了一旦word第一次匹配到了pattern,就执行对应的command-list,并且退出。
;&和;;&:而这两个是不会在第一次匹配到就立刻退出的,还会有其他后续的动作,几乎很少用到,有需要的可以去看手册。

word在匹配前会经历:波浪符展开、参数展开、命令替换、算术展开和引号去除。

pattern会经历:波浪符展开、参数展开、命令替换和算术展开。

当word的值是一个通配符的时候,表示默认的case。类似多分支if语句最后的else。

来个官方示例,简单易懂。

#!/bin/bash

echo -n "Enter the name of an animal: "
read ANIMAL
echo -n "The $ANIMAL has "
case $ANIMAL in
horse | dog | cat) echo -n "four";;
man | kangaroo ) echo -n "two";;
*) echo -n "an unknown number of";;
esac
echo " legs."

学会了case语句后,我们就可以对上面的多分支if语句的最后一个示例(显示系统信息的)进行改写,改为case语句的。应该不难,这里不演示了,我们尝试新的脚本。

我们尝试写一个bash服务类脚本,常见于CentOS 6系列的系统中的/etc/rc.d/init.d/目录下。

  • 脚本的名称一般就是服务名称,不会带“.sh”。
  • 服务脚本一般会创建一个空文件作为锁文件,若此文件存在则表示服务处于运行状态;反之,则服务处于停止状态。
  • 脚本只能接收四种参数:start, stop, restart, status。
  • 我们并不会真正启动某进程,只要echo即可。启动时需创建锁文件,停止时需删除锁文件。
  • 适当加入条件判断使得脚本更健壮。
#!/bin/bash
#
# chkconfig: -
# Description: test service script
# prog=$(basename $)
lockfile="/var/lock/subsys/$prog" case $ in
start)
if [ -e $lockfile ]; then
echo "The service $prog has already started."
else
touch $lockfile
echo "The service $prog starts finished."
fi
;;
stop)
if [ ! -e $lockfile ]; then
echo "The service $prog has already stopped."
else
rm -f $lockfile
echo "The service $prog stops finished."
fi
;;
restart)
if [ -e $lockfile ]; then
rm -f $lockfile
touch $lockfile
echo "The service $prog restart finished."
else
touch $lockfile
echo "The service $prog starts finished."
fi
;;
status)
if [ -e $lockfile ]; then
echo "The service $prog is running."
else
echo "The service $prog is not running."
fi
;;
*)
echo "Usage: $prog {start|stop|restart|status}"
exit
;;
esac

脚本编写完成后,要放入服务脚本所在的目录、给予权限、加入服务管控(chkconfig),最后就可以使用service命令进行测试了。

~]# cp -av case_service.sh /etc/rc.d/init.d/case_service
‘case_service.sh’ -> ‘/etc/rc.d/init.d/case_service’
~]# chmod a+x /etc/rc.d/init.d/case_service
~]# chkconfig --add case_service
~]# chkconfig case_service on

像这个服务类的脚本,我们在重启时,可能执行先停止后启动,也可能执行启动。这些在启动和停止时都有已经写好的代码了。如果可以将代码进行重用的话,就可以减少很多代码劳动。这就是之后要介绍的函数。

Bash脚本编程学习笔记06:条件结构体的更多相关文章

  1. Bash脚本编程学习笔记08:函数

    官方资料:Shell Functions (Bash Reference Manual) 简介 正如我们在<Bash脚本编程学习笔记06:条件结构体>中最后所说的,我们应该把一些可能反复执 ...

  2. Bash脚本编程学习笔记07:循环结构体

    本篇中涉及到算术运算,使用了$[]这种我未在官方手册中见到的用法,但是确实可用的,在此前的博文<Bash脚本编程学习笔记03:算术运算>中我有说明不要使用,不过自己忘记了.大家还是尽量使用 ...

  3. Bash脚本编程学习笔记04:测试命令test、状态返回值、位置参数和特殊变量

    我自己接触Linux主要是大学学习的Turbolinux --> 根据<鸟哥的Linux私房菜:基础篇>(第三版) --> 马哥的就业班课程.给我的感觉是这些课程对于bash的 ...

  4. Bash脚本编程学习笔记05:用户交互与脚本调试

    用户交互 在<学习笔记04>中我们有提到位置参数,位置参数是用来向脚本传递参数的一种方式.还有一种方式,是read命令. [root@c7-server ~]# read name alo ...

  5. bash脚本编程学习笔记(一)

    bash脚本语言,不同于C/C++是一种解释性语言.即在执行前不需要事先转变为可执行的二进制代码,而是每次执行时经解释器解释后执行.bash脚本语言是命令的堆砌,即按照实际需要,结合命令流程机制实现的 ...

  6. bash脚本编程学习笔记(二)

    1.脚本编程之函数 函数是实现结构化编程重要的思想,主要目的是实现代码重用 定义一个函数: function FUNCNAME { command //函数体 }   FUNCNAME(){ //函数 ...

  7. Go语言学习笔记十: 结构体

    Go语言学习笔记十: 结构体 Go语言的结构体语法和C语言类似.而结构体这个概念就类似高级语言Java中的类. 结构体定义 结构体有两个关键字type和struct,中间夹着一个结构体名称.大括号里面 ...

  8. matlab学习笔记12_3串联结构体,按属性创建含有元胞数组的结构体,filenames,isfield,isstruct,orderfields

    一起来学matlab-matlab学习笔记12 12_3 结构体 串联结构体,按属性创建含有元胞数组的结构体,filenames,isfield,isstruct,orderfields 觉得有用的话 ...

  9. 【Linux_Shell 脚本编程学习笔记一、条件表达式】

    条件表达式返回的结果都为布尔型 真为1,假为0 条件测试的表达式 [expression] 比较符 整数比较 -eq:比较两个整数是否相等,$A -eq $B -ne:测试两个整数是否不等,不等则为真 ...

随机推荐

  1. android开发实战-记账本APP(一)

    记账本开发流程: 对于一个记账本的初步开发而言,我实现的功能有: ①实现一个记账本的页面 ②可以添加数据并更新到页面中 ③可以将数据信息以图表的形式展现 (一)首先,制作一个记账本的页面. ①在系统自 ...

  2. CUDA学习(六)之使用共享内存(shared memory)进行归约求和(M个包含N个线程的线程块)

    在https://www.cnblogs.com/xiaoxiaoyibu/p/11402607.html中介绍了使用一个包含N个线程的线程块和共享内存进行数组归约求和, 基本思路: 定义M个包含N个 ...

  3. 深入了解 Java 中的异常处理 + 面试题

    # 深入了解 Java 中的异常处理 + 面试题 在程序开发中,异常处理也是我们经常使用到的模块,只是平常很少去深究异常模块的一些知识点.比如,try-catch 处理要遵循的原则是什么,finall ...

  4. 对result文件进行数据清洗以及进行可视化

    项目源码地址:https://github.com/gayu121/result(项目里操作的数据都是清洗过后的数据) 测试要求: 1. 数据清洗:按照进行数据清洗,并将清洗后的数据导入hive数据库 ...

  5. Linux磁盘管理及挂载

    1.在vm workstations添加磁盘 添加完之后重启一下虚拟机 然后fdisk -l 可以看到虚拟机已经识别到了新的磁盘 2.添加磁盘分区 输入命令 fdisk /dev/sdb 命令(输入 ...

  6. VS2017/19 在更新之后,.net core项目出一个500的神奇错误

    先说症状: VS 更新升级之后,如果用的是 .net core 的项目的时候,当vs升级时,.net core的sdk或者runtime有跟着升级的话,项目发布之后,覆盖dll到服务器时,会出现这个错 ...

  7. mplayer命令行模式下的使用方法【转】

    mplayer命令行模式下的使用方法http://hi.baidu.com/lovehack2006/blog/item/162ef9778214111eb051b9d4.htmlMPlayerMPl ...

  8. python3 控制结构知识及范例

    (一)三种基本控制结构 1.顺序结构:按照程序语句编写的顺序依次逐条执行 2.选择结构:根据特定的条件选择某一个分支 3.循环结构:反复执行某个或者某些操作,关注点:在什么情况下,反复执行哪一部分的操 ...

  9. qt creator源码全方面分析(2-6)

    目录 User Interface Text Guidelines 语法和风格 标点 编写工具提示tooltips 编写消息 UI文本大写 使用书本样式大写 使用句子样式大写 准备本地化 标记UI文本 ...

  10. java11类和对象

    import java.util.Scanner; public class jh_01_如何认识事物 { public static void main(String[] args) { Scann ...