SHELL脚本编程进阶(一)

写在前面(最重要)

本文部分资料和示例援引自以下书籍。在此,感谢原作者的创作,以及所有译者的付出,向他们致敬。

  1. Advanced Bash-Scripting Guide
  2. 《高级Bash脚本编程指南》Revision 10中文版
  3. Linux脚本编程执导

其中 《高级Bash脚本编程指南》Revision 10中文版 是 《Advanced Bash-Scripting Guide》 的中文翻译版,文档翻译正在进行中,再次感谢译者付出。

前言

在之前的文章中,我们已经详细的介绍了SHELL脚本编程的一些基础知识,运用这些基础已经能够帮助我们高效率的解决日常生产中的一些问题了,但还远远不够。实际生产中可能面临这大量的复杂的处理任务,需要我们编写脚本去完成。此时就需要一些更高级的内容,来帮助我们完成对脚本的编写。
今天将介绍的是SHELL脚本中的循环与分支

分支与循环

1. 分支

2. 循环

3. 循环控制

4. 特殊用法

分支

条件选择if语句

if 语句是脚本编写过程中基本分支语句。简单的if语句可以使用一些测试结构代替,但是if语句的可读性,却是测试结构无法替代。

单分支的if语句

单分支的 if 语句的语法结构如下。

	if 判断条件;then
		COMMANDS
		...	fi

多分支的if语句

多分支的 if 语句的语法结构如下。

	if 判断条件;then
		COMMANDS
		...	elif 判断条件;then
		COMMANDS
		...	elif 判断条件;then
		COMMANDS
		...	else		COMMANDS
		...	fi

if 语句其实还是比较好理解的,它是对某一个条件进行判断,然后根据判断的结构进行其他的操作。稍微有点编程经验的人,都会理解这种简短的分支结构。 
if 语句还可以嵌套,可以根据实际生产中的情况,合理的进行嵌套组合。

例子

  • 判断某个变量的值是否在0-5之间
# 这是一个嵌套的if语句a=3if [ "$a" -gt 0 ];then								#then 也可以写在下一行,这时就可以去掉 分号
  if [ "$a" -lt 5 ];then    echo "The value of \"a\" lies somewhere between 0 and 5."
  fi
fi# 和下面的结果相同if [ "$a" -gt 0 ] && [ "$a" -lt 5 ]then  echo "The value of \"a\" lies somewhere between 0 and 5."fi
  • 判断某个学员的学习成绩,并输出。不及格,及格,优秀等信息。
# 读取用户输入的成绩read -p "Please input your score "  SCOREif [ "$SCORE" -lt 60 ];then	echo "不及格"elif [ "$SCORE" -ge 60   -a  "$SCORE" -lt 80 ];then	echo "及格"elif [ "$SCORE" -ge 80   -a  "$SCORE" -le 100 ];then 
	echo "优秀"fi

条件判断case语句

在一些比较流行的编程语言中也有多分支的条件判断语句,例如C/C++/JAVA中的switch语句,可以根据条件跳转到其中的任意一个分支,很适合用来创建菜单。

case 语句的语法如下

	case "$variable" in
	  "$condition1" )
	    command...	  	;;
	  "$condition2" )
	    command...	  	;;
	esac

注意

  • 对变量进行引用不是必须的,因为在这里不会进行字符分割
  • 条件测试语句必须以右括号 ) 结束。
  • 每一段代码块都必须以双分号 ;; 结束。
  • 如果测试条件为真,其对应的代码块将被执行,而后整个 case 代码段结束执行
  • case 代码段必须以 esac 结束(倒着拼写case)。

case支持glob风格的通配符

  • *: 任意长度任意字符
  • ?: 任意单个字符
  • []: 指定范围内的任意单个字符
  • a|b: a或b

示例

  • 判断用户输入的 是否是yes或者no(只要是这两个词就可以,忽略大小写)
	read -p "Please input [yes/no]" INPUT	case $INPUT in
	[Yy]|[Yy][Ee][Ss])
	    echo "Your word is yes"
	    ;;
	[Nn]|[Nn][Oo])
	    echo "Your word is no"
	    ;;
	*)
	    echo "Your word is wrong"
	    ;;
	esac
  • 实现简单的通讯录,输入索引,能够查看详细的信息
#!/bin/bash#简易的通讯录数据库#清屏clearecho -e  "ContactList
-----------
Chooseoneofthefollowingpersons:

[E]vans,Roland
[J]ones,Mildred
[S]mith,Julie
[Z]ane,Morris"echo

read -p "Please choose one menu [E|J|S|Z] "  personcase "$person" in#注意变量是被引用的。"E"|"e")#同时接受大小写的输入。echo -e "
RolandEvans
4321FlashDr.
Hardscrabble,CO80753
(303)734-9874
(303)734-9892fax
[email protected]
Businesspartner&oldfriend";;#注意用双分号结束这一个选项。"J"|"j")echo -e "
MildredJones
249E.7thSt.,Apt.19
NewYork,NY10009
(212)533-2814
(212)533-9972fax
[email protected]
x-girlfriend
birthday:Feb.11";;*)#缺省设置。#空输入(直接键入回车)也是执行这一部分。echo
echo "Notyetindatabase.";;esacecho#练习:#-----#修改脚本,使得其可以循环接受多次输入而不是只显示一个地址后终止脚本。exit 0
  • 查看当前系统的设备架构 是 i386 还是i486 或者是X86_64
#!/bin/bash#  使用命令替换生成 "case" 变量。case $( arch ) in   # $( arch ) 返回设备架构。# 等价于 ‘uname -m"。i386 ) echo "80386-based machine";;i486 ) echo "80486-based machine";;i586 ) echo "Pentium-based machine";;i686 ) echo "Pentium2+-based machine";;X86_64 ) echo "X86_64-based machine";;*    ) echo "Other type of machine";;esacexit 0

select

select 语句严格来说不能算作循环,因为它们并没有反复执行代码块。但是和循环结构相似的是,它们会根据代码块顶部或尾部的条件控制程序流。
select 结构的语法如下

select variable [in list]do command... breakdone
  • 如果不使用break命令,select 语句将变成无限循环,会重复的执行那些代码段。
  • select 循环主要用于创建菜单,按数字顺序排列的菜单项将显示在标准输出上。
  • select 默认使用提示字串3(Prompt String 3,$PS3, 即#?),但同样可以被修改。
  • 用户输入菜单列表中的某个数字,执行相应的命令
  • 用户输入被保存在内置变量 REPLY 中

示例

  • 选出一个最喜欢吃的蔬菜
#!/bin/bashPS3=‘Choose your favorite vegetable: ‘  # 设置提示字串。
										# 否则默认为 #?。echoselect vegetable in "beans" "carrots" "potatoes" "onions" "rutabagas"do    echo
    echo "Your favorite veggie is $vegetable."
    echo "Yuck!"
    echo
    break  # 如果没有 ‘break‘ ,整个代码会一直循环下去,直到按了Ctrl+C 为止。doneexit

上面这段代码,会输出如下的效果

1) beans
2) carrots
3) potatoes
4) onions
5) rutabagas
Choose your favorite vegetable: 1

Your favorite veggie is beans.
Yuck!

如果省略了 [in list] 那么 select 将会使用传入脚本的命令行参数([email protected])或者传入函数的参数作为 list。可以与 for variable [in list] 中 in list 被省略的情况做比较。
下面将省略 这个列表来实现上面的例子。 运行效果与上面的结果是一致的。

#!/bin/bashPS3=‘Choose your favorite vegetable: ‘echochoice_of(){select vegetable# [in list] 被省略,因此 ‘select‘ 将会使用传入函数的参数作为 list。do  echo
  echo "Your favorite veggie is $vegetable."
  echo "Yuck!"
  echo
  breakdone}choice_of beans rice carrorts radishes rutabaga spinach#         $1    $2   $3      $4       $5       $6#         传入了函数 choice_of()exit 0

循环

循环,顾名思义就是重复性的执行某一基本操作。在Linux/Bash 中有三种基本循环,for,while,until循环。

for 循环 for arg in [list]

for 循环 可以有以下的列表生成方式

  • 直接给出列表
for var in item1 item2 ... itemNdo	command1
    command2
    ....
    ...
    commandNdone
  • 直接给出一个整数列表
# 直接给出整数列表  for var in 1 2 3 4 ... 100do	command1
    command2
    ....
    ...
    commandNdone# 或者直接生成整数列表  for var in {1..100..2}do	command1
    command2
    ....
    ...
    commandNdone# 或者直接生成整数列表  for var in $(seq 0  2  100)   ##seq [start [step]] end do	command1
    command2
    ....
    ...
    commandNdone
  • 能够返回列表的命令
# 直接给出整数列表  for var in $(ls *)do	command1
    command2
    ....
    ...
    commandNdone
  • 使用glob 如 *.sh ,便是当前目录下的.sh文件列表
for var in *.shdo	command1
    command2
    ....
    ...
    commandNdone
  • 直接使用某个变量引用 如[email protected],$* ,或者某个变量
fileNames="HELLO1  HELLO2  HELLO3  HELLO4"for var in $fileNamesdo    command1
    command2
    ....
    ...
	commandNdone
  • 也可以直接遍历某个数组
ArrayName=(/etc/*.conf)for var in ${ArrayName[@]}do    command1
    command2
    ....
    ...
	commandNdone

示例

检查某些指定的文件是否存在

#!/bin/bash# fileinfo.shFILES="/usr/sbin/accept
/usr/sbin/pwck
/usr/sbin/chroot
/usr/bin/fakefile
/sbin/badblocks
/sbin/ypbind"     # 你可能会感兴趣的一系列文件。
                  # 包含一个不存在的文件,/usr/bin/fakefile。echofor file in $FILESdo

  if [ ! -e "$file" ]       # 检查文件是否存在。
  then    echo "$file does not exist."; echo    continue                # 继续判断下一个文件。
  fi  echodoneexit 0

while 循环

Bash中的while循环结构与其他编程语言的while循环结构一致的,在循环的开始就判断条件是否满足,如果循环条件为真,就继续执行循环,如果为假则跳出循环。
其语法结构如下

while [ condition ]do  	command1
	...
	commandNdone
  • CONDITION:循环控制条件;进入循环之前,先做一次判断;每一次循环之后会再次做判断;条件为“true”,则执行一次循环;直到条件测试状态为“false”终止循环。
  • 因此:CONDTION一般应该有循环控制变量;而此变量的值会在循环体不断地被修正。
  • 进入条件:CONDITION为true
  • 退出条件:CONDITION为false
  • while循环的括号结构不是必须存在的

示例:简单的while循环

#!/bin/bashvar0=0LIMIT=10while [ "$var0" -lt "$LIMIT" ]do  echo -n "$var0 "        # -n 不会另起一行

  var0=`expr $var0 + 1`   # var0=$(($var0+1))  效果相同。
                          # var0=$((var0 + 1)) 效果相同。
                          # let "var0 += 1"    效果相同。done                      # 还有许多其他的方法也可以达到相同的效果。

示例:多测试条件的while循环

一个 while 循环可以有多个测试条件,但只有最后的那一个条件决定了循环是否终止。这是一种你需要注意到的不同于其他循环的语法。

#!/bin/bashvar1=unsetprevious=$var1while echo "previous-varialbe = $previous"
      echo      previous=$var1 		 # 记录下 $var1 之前的值。
      [ "$var1" != end ]  
		# 在 while 循环中有4个条件,但只有最后的那个控制循环。
     	# 最后一个条件的退出状态才会被记录。doecho "Input variable #1 (end to exit)" read var1echo "variable #1 = $var1"doneexit 0

示例:在 while 循环中结合 read 命令,我们就得到了一个非常易于使用的 while read 结构。它可以用来读取和解析文件 。

while read value   # 一次读入一个数据。do    echo "The value is $value"done

until

与while循环相反,until循环是其测试条件为真时,跳出循环。也就是说,测试条件为假,进入循环,测试条件为真退出循环。 而且,与其他编程语言不一样的地方在于,until循环的测试条件在循环的顶部。 语法如下所示

until [ condition-is-true ]do  commands(s)...done

示例:读取用户输入,并输出到标准输出上,如果是end结束

#!/bin/bashEND_CONDITION=enduntil [ "$var1" = "$END_CONDITION" ]# 在循环顶部测试条件。do  echo "Input variable #1 "
  echo "($END_CONDITION to exit)"
  read var1  echo "variable #1 = $var1"
  echodone

循环控制 break,continue,shift

break [N],continue [N]

break 和 continue 命令的作用和其他编程语言中的作用一样。break 是跳出结束循环,continue是跳出本次循环,进入到下一次循环。
但是 ,在bash 中,break 和 continue 有一种特殊用法,能够指定跳出其上 N 层的循环,也就是 continue [N]

接下来我们使用一个示例来演break和continue的使用。

#!/bin/bash# "continue N" 命令可以影响其上 N 层循环。for outer in I II III IV V           # 外层循环do  echo; echo -n "Group $outer: "

  # --------------------------------------------------------------------
  for inner in 1 2 3 4 5 6 7 8 9 10  # 内层循环
  do

    if [[ "$inner" -eq 7 && "$outer" = "III" ]]
    then
      continue 2  # 影响两层循环,包括“外层循环”。
                  # 将其替换为普通的 "continue",那么只会影响内层循环。
    fi    echo -n "$inner "  # 7 8 9 10 将不会出现在 "Group III."中。
  done
  # --------------------------------------------------------------------doneexit 0

shift [N]

用于将参量列表左移指定次数,默认是左移1次。 
参量列表 list 一旦被移动,最左端的那个参数就从列表中删除。while 循环遍历位置参量列表时,常用到 shift。

示例:批量添加用户,并能够根据输入的选项,进行不同的输出

# 使用示例# ./user.sh  --add MAGE,WANG,HELLO -v# ./user.sh  -h#!/bin/bashDEBUG=0ADD=0DEL=0for I in `seq  $#`; do
case $1 in-v|--verbose)
    DEBUG=1			#是否用来输出详情
    shift			# 参数列表向左 移动 1 个
    ;;-h|--help)
    echo "Usage:`basename $0` --add USER_LIST --del USER_LIST -v|--verbose -h|--help"
    exit 0    ;;--add)
    ADD=1    ADDUSERS=$2
    shift 2    ;;--del)
    DEL=1    DELUSERS=$2
    shift 2    ;;esacdone

if [ $ADD -eq 1 ]; then
    for USER in `echo $ADDUSERS | sed ‘[email protected],@ @g‘`; do	#将用户列表分割
        if id $USER &> /dev/null; then
            [ $DEBUG -eq 1 ] && echo "$USER exists"
        else            useradd $USER
            [ $DEBUG -eq 1 ] && echo "Add user $USER finished."
        fi
     done      
fi

if [ $DEL -eq 1 ]; then
    for USER in `echo $DELUSERS | sed ‘[email protected],@ @g‘`; do
        if id $USER &> /dev/null; then            userdel -r $USER
            [ $DEBUG -eq 1 ] && echo "Delete user $USER finished "
        else
            [ $DEBUG -eq 1 ] && echo "user $USER not exists."
        fi
    done      
fi

特殊用法

  • 双小括号方法,即((…))格式,也可以用于算术运算,双小括号方法也可以使bash Shell实现C语言风格的变量操作。for循环和while循环都可以使用这种((…))格式

** for 循环 的语法格式如下 **

for ((EXPR1;EXPR2;EXPR3));do	COMMAND
	....
	COMMANDdone# 例如 输出 1-10LIMIT=10for ((a=1; a <= LIMIT ; a++))  # 双圆括号语法,不带 $ 的 LIMITdo  echo -n "$a "done

until循环的语法如下

until (( EXPR ));do	COMMAND
	....
	COMMANDdone#例输出 0-10 LIMIT=10var=0until (( var > LIMIT ))do  # ^^ ^     ^     ^^   没有方括号,没有 $ 前缀。
  echo -n "$var "
  (( var++ ))done    # 0 1 2 3 4 5 6 7 8 9 10

while循环的语法如下

while (( EXPR1 ))   #  双圆括号结构,do                       
 
done#例如 实现1-10 的和LIMIT=10while (( a <= LIMIT ))   #  双圆括号结构,do                       #+ 并且没有使用 "$"。
  echo -n "$a "
  ((a += 1))             # let "a+=1"
  # 是的,就是这样。
  # 双圆括号结构允许像C语言一样自增一个变量。done
  • while 循环的特殊用法(遍历文件的每一行)
#依次读取/PATH/FROM/SOMEFILE文件中的每一行,且将行赋值给变量linewhile read line; do	循环体done < /PATH/FROM/SOMEFILE

在实际的使用过程中,可以实现多种循环的嵌套,以便实现复杂任务,应当具体情况具体分析。

如何在 for,while 和 until 之间做出选择?我们知道在C语言中,在已知循环次数的情况下更加倾向于使用 for 循环。但是在Bash中情况可能更加复杂一些。Bash中的 for 循环相比起其他语言来说,结构更加松散,使用更加灵活。因此使用你认为最简单的就好。

个人博客地址:http://www.pojun.tech/ 欢迎访问

时间: 2024-11-10 13:26:14

SHELL脚本编程进阶(一)的相关文章

shell脚本编程进阶练习题

这两天学习了shell脚本编程进阶,作为一枚文科生,小编觉得...恩..脚本很烧脑.....,不过小编还是做了些题,稍作总结后,呈给各位看官,内容如下: 一.条件选择if语句 选择执行: 注意:if语句可嵌套 单分支 if 判断条件;then 条件为真的分支代码 fi 双分支 if 判断条件; then 条件为真的分支代码 else 条件为假的分支代码 fi 多分支 if 判断条件1; then 条件为真的分支代码 elif 判断条件2; then 条件为真的分支代码 elif 判断条件3; t

SHELL脚本编程进阶(二)

写在前面(最重要) 本文部分资料和示例援引自以下书籍.在此,感谢原作者的创作,以及所有译者的付出,向他们致敬. Advanced Bash-Scripting Guide <高级Bash脚本编程指南>Revision 10中文版 Linux脚本编程执导 其中 <高级Bash脚本编程指南>Revision 10中文版 是 <Advanced Bash-Scripting Guide> 的中文翻译版,文档翻译正在进行中,再次感谢译者付出. 前言 在之前的文章 Linux 基

shell脚本编程进阶

前言:进入正题之前我们先来复习一下有关脚本编程的条件测试 一,流程控制 过程式编程语言 a.顺序执行 b.选择执行 c.循环执行 顺序执行 顾名思义,就是按照你脚本里所敲的内容顺序执行 选择执行 fi a.条件选择if语句,可以嵌套 b.格式 单支 if 判断条件;then 条件为真 fi 双分支 if 判断条件;then 条件为真 else 条件为假 fi 多分支 if 判断条件;then 条件为真 elif(相当于else if) 判断条件;then 条件为真 else 上述条件都为假 fi

第14章,Shell脚本编程进阶

更多内容请点击: Linux学习从入门到打死也不放弃,完全笔记整理(持续更新,求收藏,求点赞~~~~) http://blog.51cto.com/13683480/2095439 本章内容: 条件判断 循环 信号捕捉 函数 数组 高级字符串操作 高级变量 Expect 过程式编程语言执行方式: 顺序执行,选择执行,循环执行 条件选择----------------------------------------------------------------------- if语句: 结构: 

shell脚本编程——进阶篇(真刀实干)

条件测试 文件测试 整数测试 字符串与逻辑测试 if语句 if单分支语句 if双分支语句 if多分支语句 if嵌套语句 test命令测试特定的表达式 是否成立,当条件成立时,测试语句的返回值为0,否则为其他数值. 格式1:test 条件表达式 格式2:[ 条件表达式 ] (注意前后至少有1个空格,否则不予执行) 文件测试格式:[ 操作符 文件或目录 ]常用的测试操作符:1.-d:测试是否为目录(Directory)2.-e:测试目录或文件是否存在(Exist)3.-f:测试是否为文件(File)

《Linux命令行与shell脚本编程大全》学习笔记(转)

第一部分:Linux命令行<Linux命令行与shell脚本编程大全> 第一章:初识Linux shell<Linux命令行与shell脚本编程大全> 第二章:走进shell<Linux命令行与shell脚本编程大全> 第三章:基本的bash shell命令<Linux命令行与shell脚本编程大全> 第四章:更多的bash shell命令<Linux命令行与shell脚本编程大全> 第五章:使用Linux环境变量<Linux命令行与she

《Linux命令行与Shell脚本编程大全第2版.布卢姆》pdf

下载地址:网盘下载 内容简介  · · · · · · 本书是一本关于Linux 命令行与shell 脚本编程的全面教程.全书分为四部分:第一部分介绍Linuxshell 命令行:第二部分介绍shell 脚本编程基础:第三部分深入探讨shell 脚本编程的高级内容:第四部分介绍如何在现实环境中使用shell 脚本.本书不仅涵盖了详尽的动手教程和现实世界中的实用信息,还提供了与所学内容相关的参考信息和背景资料. 本书内容全面,语言简练,示例丰富,适合于linux 系统管理员及Linux 爱好者阅读

shell脚本编程高级篇

SHELL脚本编程进阶循环执行:简单来说就是把一些指令重复循环. 循环代码具体的指令有三种: for , while , until其中for, while用的最多.for循环 for 变量名 in 列表;do 循环体 done 关键字的帮助都是用help来查询.for循环语法:在shell编程中 for,in,do,done.这些都是他的关键字,其中循环的指零就放在do和done之间.WORDS决定了循环次数.循环的次数由in 后面跟的WORDS(字符串)的数量决定.字符串的个数决定了do和d

shell脚本基础进阶(四)----作业

20150913-15作业 1.描述shell程序的运行原理(可附带必要的图形说明) shell脚本基础进阶(一)----shell介绍 2.总结shell编程中所涉及到的所有知识点(如:变量.语法.命令状态等等等,要带图的哟) shell脚本基础进阶(二)----变量及运算符 3.总结课程所讲的所有循环语句.条件判断的使用方法及其相关示例:(if (jpg|png is not exist):echo "You say a XX") shell脚本基础进阶(三)----流程控制语句