小小千想和您聊一聊

当前位置: 首页> 技术分享> 第2章 Shell编程

第2章 Shell编程

  本章学习目标

  l 理解Shell的概念

  l 掌握Shell的编程

  l 了解Shell的调试

  Shell是一个作为用户与Linux内核通信的桥梁,它除了解释用户向操作系统输入的命令外,还可以调用其他程序或被其他程序调用,因此,Shell将内核、程序和用户连接在一起。

  2.1 Shell简介

  Shell既是一种命令语言,又是一种程序设计语言。Shell 脚本是使用Shell编程语言编写的脚本语言,主要用于实现系统管理的功能。在一个Linux系统中可以安装多个Shell,默认安装的是bash,可以使用echo命令查看系统使用的Shell类型,具体如下所示:

  [root@qfedu ~]# echo $SHELL

  /bin/bash

  接下来通过一个简单案例演示Shell脚本的编写及运行,具体如下所示:

  (1)使用Vim编辑器编写如下代码。

  [root@qfedu ~]# vim test.sh

  #!/bin/bash

  #输出"Hello World!"

  echo "Hello world!"

  第1行中,“#!/bin/bash”是一种约定的标记,它指定系统使用何种解释器执行该脚本;第2行中,#表示该行是一条注释,它与第1行中#的含义不同。另外,Shell脚本文件的名称可以任意,但为了与其他文件进行区分,建议加上后缀(.sh)用来表示是一个Shell脚本文件。

  (2)为脚本文件增加执行权限。

  [root@qfedu ~]# chmod u+x test.sh

  (3)执行脚本文件。

  [root@qfedu ~]# ./test.sh

  Hello world!

  此外,在命令行通过添加解释器也可以执行脚本文件,具体如下所示。

  [root@qfedu ~]# /bin/bash test.sh

  Hello world!

  2.2 变量

  2.2.1 变量的定义与访问

  变量是编程中最基本的单元,它会暂时引用用户需要存储的数据,例如,小千的年龄是18,就可以使用变量来引用18,具体如下所示:

  age=18

  其中,age为变量名,18为变量值,=为赋值运算符。注意,变量名和赋值运算符之间不能有空格。同时,变量名的命名须遵循如下规则。

  (1)只能使用英文字母、数字和下画线,且不能以数字开头。

  (2)中间不能有空格。

  (3)不能使用bash中的关键字(可使用help命令查看bash保留的关键字)。

  若需要访问变量,则必须在变量名前添加$符号,具体如下所示:

  echo $age

  18

  除了显式地给变量赋值外,使用语句也可以给变量赋值,具体如下所示:

  age=`expr 16 + 2`

  以上语句将 16 + 2的值赋给变量age,注意反引号中的空格必须存在。

  2.2.2 只读变量

  只读变量是指值不能被改变的变量,使用 readonly 命令可以将变量定义为只读变量,具体如下所示:

  #!/bin/bash

  age=18

  readonly age

  age=20

  当执行该脚本时,输出如下内容:

  ./test.sh: line 4: age: readonly variable

  第4行赋值语句试图修改只读变量的值,此操作不可成功执行。

  2.2.3 删除变量

  unset命令可以删除变量,具体如下所示:

  age=18

  unset age

  echo $age

  当执行上述脚本时,无任何内容输出,证明变量删除成功。注意,unset 命令不能删除只读变量。

  2.3 字符串

  2.3.1字符串表示形式

  字符串是Shell编程中最常用的数据类型,可以使用3种形式表示。

  1. 单引号形式

  name='xiaoqian'

  在使用此形式表示字符串时,需注意以下几点。

  l 单引号中的任何字符都会原样输出。

  l 单引号字符串中的变量是无效的。

  l 单引号字符串中不能出现单引号。

  2. 双引号形式

  name="xiaoqian"

  str="Her name is $name"

  echo $str

  当执行该脚本时,输出如下内容。

  Her name is xiaoqian

  双引号表示的字符串中可以存在变量,当访问该字符串时,程序会解析其中的变量。如果字符串中变量前添加了符号\,则程序不会解析其中的变量,具体如下所示:

  name="xiaoqian"

  str="\$name is a variable"

  echo $str

  当执行该脚本时,输出如下内容:

  $name is a variable

  如果双引号形式的字符串中包含双引号字符,也需要在双引号前添加\,具体如下所示:

  name="xiaoqian"

  str="\"$name\""

  3. 无引号形式

  name=xiaoqian

  echo $name

  当执行该脚本时,输出如下内容。

  xiaoqian

  2.3.2 字符串处理

  在编程时,字符串经常需要被处理,例如,求字符串的长度、查找子字符串等。接下来讲解几种常用的字符串处理方式,具体如下。

  1. 获取字符串长度

  name="xiaoqian"

  echo ${#name} # 输出8

  其中,${#name}表示字符串name的长度。

  2. 提取子字符串

  name="xiaoqian"

  echo ${name:4:4} # 输出qian

  其中,${name:4:4}表示从字符串name的第 5个字符开始截取4个字符。

  3. 查找子字符串

  name="xiaoqian"

  echo `expr index "$name" a` # 输出3

  echo `expr index "$name" ai` # 输出2

  其中,第2行表示查找第一次字符a出现的位置,位置从1开始计算,如果返回0,则表示查找失败;第3行表示查找字符a或i出现的位置。

  2.4 数组

  数组是Shell中非常重要的组成部分,它借助索引将多个独立的数据存储为一个集合。数组分为普通数组和关联数组,普通数组只能使用整数作为数组索引,而关联数组可以使用字符串作为数组索引。

  2.4.1 数组的定义

  数组使用一对圆括号表示,数组元素之间用空格符号分割,具体如下所示:

  array1=(1 2 3)

  array2=("xiaoqian" "xiaofeng")

  此外,数组还可以定义为一组索引-值的形式,具体如下所示:

  array3[0]=1

  array3[1]=2

  array3[4]=3

  注意,索引值可以不连续,而且范围没有限制。

  以上是普通数组的定义,关联数组在定义前首先需要使用声明语句进行声明,具体如下所示:

  declare -A array4

  array4=([xiaoqian]=18 [xiaofeng]=19)

  declare -A array5

  array5[xiaoqian]=18

  array5[xiaofeng]=20

  2.4.2 数组的操作

  数组定义完成后,就可以对其进行一些操作,具体如下所示:

  1. 获取数组长度

  echo ${#array1[*]} #输出3

  echo ${#array4[@]} #输出2

  上述2种方法都可以获取数组的长度,与获取字符串长度的方法类似。此外,获取数组中单个元素的长度可以使用如下方法:

  echo ${#array2[0]} # 输出8

  echo ${#array5[xiaoqian]} # 输出2

  2. 获取数组元素值

  echo ${array1[0]} # 输出1

  echo ${array4[xiaoqian]} # 输出18

  上述语句是获取数组中单个元素值,若需要获取数组中所有元素值,可以使用@或者*符号,具体如下所示:

  echo ${array1[*]} # 输出1 2 3

  echo ${array4[@]} # 输出19 18

  3. 获取数组索引

  echo ${!array1[*]} # 输出0 1 2

  echo ${!array4[@]} # 输出xiaofeng xiaoqian

  上述2种方法都可以获取数组的全部索引。

  2.5 运算符

  Shell支持多种运算符,包括算术运算符、关系运算符、布尔运算符、字符串运算符、文件测试运算符。原生bash不支持简单的数学运算,但是可以通过其他命令来实现,例如expr。expr 是一款表达式计算工具,使用它可以完成表达式的求值操作。

  2.5.1 算术运算符

  若变量 a 为 1,变量 b 为 2,则关于a与b的算术运算,如表2.1所示。

  表2.1 算术运算符

  在表2.1中,乘号(*)前面必须加反斜杠(\)才能实现乘法运算,条件表达式需要放在方括号之间,左右各有1个空格,具体如下所示:

  a=1

  b=2

  val=`expr $a + $b`

  echo "$a + $b = $val"

  val=`expr $a - $b`

  echo "$a - $b = $val"

  val=`expr $a \* $b`

  echo "$a * $b = $val"

  val=`expr $a / $b`

  echo "$a / $b = $val"

  val=`expr $a % $b`

  echo "$a % $b = $val"

  if [ $a == $b ]

  then

  echo "$a等于$b"

  fi

  if [ $a != $b ]

  then

  echo "$a 不等于 $b"

  fi

  当执行该脚本时,输出如下内容:

  1 + 2 = 3

  1 - 2 = -1

  1 * 2 = 2

  1 / 2 = 0

  1 % 2 = 1

  1 不等于 2

  2.5.2 关系运算符

  关系运算符只支持数字或字符串的值是数字。若变量 a 为 1,变量 b 为 2,则关于a与b的关系运算如表2.2所示。

  表2.2 关系运算符

  接下来演示关系运算符的使用,具体如下所示:

  a=1

  b=2

  if [ $a -eq $b ]

  then

  echo "$a -eq $b : $a等于$b"

  else

  echo "$a -eq $b : $a不等于$b"

  fi

  当执行该脚本时,输出如下内容:

  1 -eq 2 : 1不等于2

  2.5.3 逻辑运算符

  若变量 a 为 1,变量 b 为 2,则关于a与b的逻辑运算如表2.3所示。

  表2.3 逻辑运算符

  在表2.3中,||和&&参与运算时,条件表达式需添加两个中括号。

  接下来演示逻辑运算符的使用,具体如下所示:

  a=1

  b=2

  if [ !false ]

  then

  echo "!false返回true"

  fi

  if [ $a -lt 10 -o $b -gt 10 ]

  then

  echo "$a -lt 10 -o $b -gt 10 : 返回true"

  else

  echo "$a -lt 10 -o $b -gt 10 : 返回false"

  fi

  if [[ $a -lt 10 || $b -gt 10 ]]

  then

  echo "$a -lt 10 || $b -gt 10 : 返回true"

  else

  echo "$a -lt 10 || $b -gt 10 : 返回false"

  fi

  if [ $a -lt 10 -a $b -gt 10 ]

  then

  echo "$a -lt 10 -a $b -gt 10 : 返回true"

  else

  echo "$a -lt 10 -a $b -gt 10 : 返回false"

  fi

  if [[ $a -lt 10 && $b -gt 10 ]]

  then

  echo "$a -lt 10 && $b -gt 10 : 返回true"

  else

  echo "$a -lt 10 && $b -gt 10 : 返回false"

  fi

  当执行该脚本时,输出如下内容。

  !false返回true

  1 -lt 10 -o 2 -gt 10 : 返回true

  1 -lt 10 || 2 -gt 10 : 返回true

  1 -lt 10 -a 2 -gt 10 : 返回false

  1 -lt 10 && 2 -gt 10 : 返回false

  2.5.4 字符串运算符

  若变量 a 为"ab",变量 b 为"cd",则关于a与b的字符串运算如表2.4所示。

  表2.4 逻辑运算符

  接下来演示字符串运算符的使用,具体如下所示:

  a="ab"

  b="cd"

  if [ $a = $b ]

  then

  echo "$a = $b : $a等于$b"

  else

  echo "$a = $b : $a不等于$b"

  fi

  if [ -z $a ]

  then

  echo "-z $a : 字符串长度为0"

  else

  echo "-z $a : 字符串长度不为0"

  fi

  if [ -n $a ]

  then

  echo "-n $a : 字符串长度不为0"

  else

  echo "-n $a : 字符串长度为0"

  fi

  if [ $a ]

  then

  echo "$a : 字符串不为空"

  else

  echo "$a : 字符串为空"

  fi

  其中,[ $a ]表示检测字符串是否为空,不为空返回true,否则返回false。当执行该脚本时,输出如下内容:

  ab = cd : ab不等于cd

  -z ab : 字符串长度不为0

  -n ab : 字符串长度不为0

  ab : 字符串不为空

  2.5.5 文件测试运算符

  文件测试运算符用于检测文件的各种属性,具体如表2.5所示。

  表2.5 文件测试运算符

  若在当前目录下存在一个文件名为test.txt的文件,该文件可读、可写、不可执行,接下来通过文件测试运算符检测该文件的某些属性,具体如下所示:

  file="./test.txt"

  if [ -e $file ]

  then

  echo "文件存在"

  else

  echo "文件不存在"

  fi

  if [ -f $file ]

  then

  echo "文件为普通文件"

  else

  echo "文件为特殊文件"

  fi

  if [ -x $file ]

  then

  echo "文件可执行"

  else

  echo "文件不可执行"

  fi

  当执行该脚本时,输出如下内容:

  文件存在

  文件为普通文件

  文件不可执行

  2.6 流程控制

  Shell编程中流程控制结构包括顺序结构、选择结构和循环结构,它们都是通过控制语句实现的。其中顺序结构不需要特殊的语句,选择结构需要通过条件语句实现,循环结构需要循环语句实现。

  2.6.1 条件语句

  前面讲解运算符时,已多次使用条件语句。条件语句分为if语句与case语句,接下来分别对其进行讲解。

  1. if语句

  最简单的if语句格式如下所示:

  if [ 条件命令 ]

  then

  命令1

  命令2

  ...

  fi

  上述语句还可以写成如下形式:

  if [ 条件命令 ]; then

  命令1

  命令2

  ...

  fi

  程序首先执行条件命令,若条件命令的返回值为true,执行命令的语句体,否则,不执行命令的语句体。

  2. if-else-fi语句

  if-else-fi语句是一种双分支选择结构,其语法格式如下:

  if [ 条件命令 ]; then

  命令列表1

  else

  命令列表2

  fi

  程序首先执行条件命令,若条件命令的返回值为true,执行命令列表1,否则,执行命令列表2。

  3. if-elif-fi语句

  if-elif-fi语句是一种多分支选择结构,其语法格式如下:

  if [ 条件命令1 ]; then

  命令列表1

  elif [ 条件命令2 ]; then

  命令列表2

  ...

  else

  命令列表n

  fi

  接下来演示if-elif-fi语句的用法,具体如下所示:

  a=1

  b=2

  if [ $a -eq $b ]; then

  echo "$a == $b"

  elif [ $a -gt $b ]; then

  echo "$a > $b"

  else

  echo "$a < $b"

  fi

  当执行该脚本时,输出如下内容:

  1 < 2

  4. case语句

  case语句也是一种多分支选择结构,其语法格式如下:

  case 变量值 in

  模式1)

  命令列表1;;

  模式2)

  命令列表2;;

  ...

  esac

  其中,模式可以有以下几种形式,如表2.6所示。

  表2.6 模式匹配

  接下来演示case语句的用法,具体如下所示:

  read -p "请输入小时:" hour

  case $hour in

  08|09|10|11|12)

  echo "早上好!";;

  13|14|15|16|17)

  echo "下午好!";;

  18|19|20|21|22)

  echo "晚上好!";;

  *)

  echo "您好!";;

  esac

  其中,read命令可以读取用户输入的值,并与对应的变量名建立关联。

  当执行该脚本时,若输入16,则输出如下内容:

  请输入小时:16

  下午好!

  2.6.2 循环语句

  循环语句分为for循环语句、while循环语句和until循环语句,接下来分别对其进行讲解。

  1. for循环语句

  for循环常用来处理简单的、确定次数的循环过程,其语法格式如下:

  for 变量 in 列表

  do

  命令列表

  done

  其中,列表可以是命令替换、变量名替换、字符串和文件名,每个列表项以空格间隔,执行循环时,列表项依次赋给循环变量。

  接下来演示for语句的用法,具体如下所示:

  for x in 1 2 3 # for x in {1..3}、for x in $(seq 3)、for x in `seq 3`

  do

  echo $x

  done

  当执行该脚本时,输出如下内容:

  1

  2

  3

  注意区分以下for语句,具体如下所示:

  for x in x1 x2 x3

  do

  echo $x

  done

  for x in "x1 x2 x3"

  do

  echo $x

  done

  当执行该脚本时,输出如下内容:

  x1

  x2

  x3

  x1 x2 x3

  另外,for循环语句也可以写成类似C语言中的形式,其语法格式如下:

  for ((expr1;expr2;expr3))

  do

  命令列表

  done

  程序首先执行expr1,若expr2的值为true,则进入循环,在执行循环体后,执行expr3;若expr2的值为false,则退出循环。

  接下来演示使用for语句求1~100的和,具体如下所示:

  sum=0

  for ((i=1;i<=100;i++))

  do

  sum=`expr $sum + $i`

  done

  echo "1 + 2 + ... + 100 = $sum"

  当执行该脚本时,输出如下内容:

  1 + 2 + ... + 100 = 5050

  2. while循环语句

  while循环语句是当条件为true时进入循环体,执行命令列表,直到条件为false时退出循环,其语法格式如下:

  while [ 条件命令 ]

  do

  命令列表

  done

  接下来演示while语句的用法,具体如下所示:

  sum=0

  i=1

  while [ $i -le 100 ]

  do

  sum=`expr $sum + $i`

  i=`expr $i + 1`

  done

  echo "1 + 2 + ... + 100 = $sum"

  当执行该脚本时,输出如下内容:

  1 + 2 + ... + 100 = 5050

  3. until循环语句

  until循环语句在条件为false时进入循环体,执行命令列表,直至条件为true时才退出循环,其语法格式如下:

  until [ 条件命令 ]

  do

  命令列表

  done

  接下来演示until语句的用法,具体如下所示:

  sum=0

  i=1

  until [ $i -gt 100 ]

  do

  sum=`expr $sum + $i`

  i=`expr $i + 1`

  done

  echo "1 + 2 + ... + 100 = $sum"

  当执行该脚本时,输出如下内容:

  1 + 2 + ... + 100 = 5050

  上面讲解了3种循环语句的基本实现,有时需要对循环进行控制,则可以使用break语句与continue语句。

  1. break语句

  break语句用于强行退出当前循环,具体如下所示:

  while [ 1 ]

  do

  read -p "请输入1~5之间的一个整数:" num

  case $num in

  1|2|3|4|5)

  echo "输入正确!";;

  *)

  echo "输入错误!"

  break;;

  esac

  done

  程序执行时,如果输入不是1~5之间的整数,程序输出“输入错误!”后,不再执行循环体语句。

  2. continue语句

  continue语句跳过本次循环的剩余部分,继续下一次循环,具体如下所示:

  while [ 1 ]

  do

  read -p "请输入1~5之间的一个整数:" num

  case $num in

  1|2|3|4|5)

  echo "输入正确!"

  break;;

  *)

  echo "输入错误!"

  continue;;

  esac

  done

  程序执行时,如果输入不是1~5之间的整数,程序输出“输入错误!”后,进入下一次循环。

  2.7 函数

  程序都是由一系列语句组成的,这些语句都是为了实现某个具体的功能。如果这个功能在整个应用中会经常使用,则每一处需要该功能的位置都写上同样的代码,必将造成大量的冗余代码,不便于后期维护。为此,Shell中引入函数的概念,程序可以重复调用函数。

  2.7.1 函数的定义及调用

  函数定义的语法格式如下。

  function 函数名() {

  命令列表

  }

  其中,function可以省略不写。

  接下来定义一个简单的函数,具体如下所示:

  function output() {

  echo "拼搏到无能为力,坚持到感动自己!"

  }

  当需要调用该函数时,则可以使用以下语句:

  output

  注意,如果函数与调用它的主程序位于同一个文件中,则函数的定义必须出现在调用之前;如果函数与调用它的主程序位于不同文件中,则先使用source命令执行保存函数定义的文件,再调用其中的函数。

  2.7.2 函数参数

  在Shell中,调用函数时可以向其传递参数。在函数体内部,通过 ${n} 的形式来获取参数的值,例如,${1}表示第1个参数,${2}表示第2个参数,依此类推。

  接下来演示函数参数的用法,具体如下所示:

  #!/bin/bash

  function add() {

  a=${1}

  b=${2}

  c=`expr $a + $b`

  echo "$a + $b = $c"

  }

  若上述脚本在文件test.sh中,则在终端输入以下命令:

  [root@qfedu ~]# source test.sh

  [root@qfedu ~]# add 12 34

  12 + 34 = 46

  此外,还有几个特殊字符用于处理参数,如表2.7。

  表2.7 特殊参数

  接下来演示特殊参数的用法,具体如下所示:

  #!/bin/bash

  function mytest() {

  echo "\$# : $#"

  for i in "$*"; do

  echo $i

  done

  for i in "$@"; do

  echo $i

  done

  echo "\$? : $?"

  }

  若上述脚本在文件test.sh中,则在终端输入以下命令:

  [root@qfedu ~]# source test.sh

  [root@qfedu ~]# mytest 4 5 6

  $# : 3

  4 5 6

  4

  5

  6

  $? : 0

  2.7.3 函数返回值

  有时脚本执行完成后需要返回特定值来完成后续操作,这些特定值就是函数返回值。在Shell编程中,函数通过return返回其退出状态,0表示无错误,1表示有错误,因此,在脚本中可以有选择地使用return语句。

  接下来演示函数返回值的用法,具体如下所示:

  #!/bin/bash

  function mytest() {

  read -p "请输入1或2:" num

  case $num in

  1|2)

  echo "输入正确!"

  return 0;;

  *)

  echo "输入错误!"

  return 1;;

  esac

  }

  若上述脚本在文件test.sh中,则在终端输入以下命令:

  [root@qfedu ~]# source test.sh

  [root@qfedu ~]# mytest

  请输入1或2:9

  输入错误!

  [root@qfedu ~]# echo $?

  1

  其中,$i用于显示函数调用结束时的退出状态。

  2.8 文件包含

  与其他语言类似,Shell 也可以包含其他外部脚本文件,这样可以很方便地封装一些公用的代码作为一个独立的文件。

  文件包含的方式有2种,具体如下所示:

  . 文件名 #.与文件名之间至少有一个空格

  source 文件名

  接下来演示文件包含的用法,具体如下所示:

  test1.sh文件内容如下。

  #!/bin/bash

  function mytest() {

  echo "拼搏到无能为力,坚持到感动自己!"

  }

  test2.sh文件内容如下。

  #!/bin/bash

  . /root/test1.sh

  mytest

  在终端执行test2.sh脚本,具体如下所示:

  [root@qfedu ~]# ./test2.sh

  拼搏到无能为力,坚持到感动自己!

  2.9 调试

  任何语言编程都有对应的调试工具,如Java有Debug工具。Shell也不例外,也提供了几种方法对程序进行调试,具体如下所示。

  1. 语法检查

  Shell的语法检查允许用户在执行程序前先检查程序的语法,但不执行命令,其语法格式如下:

  sh -n 文件名

  若test.sh文件内容如下:

  #!/bin/bash

  for i in 1 2 3

  echo $i

  done

  在终端下输入以下命令:

  [root@qfedu ~]# sh -n test.sh

  test.sh: line 3: syntax error near unexpected token `echo'

  test.sh: line 3: ` echo $i'

  上述输出内容提示在echo附近出现语法错误,此处缺少do关键字。

  2. 普通调试

  Shell的普通调试允许用户观察程序的执行,其语法格式如下。

  sh -x 文件名

  若test.sh文件内容如下:

  #!/bin/bash

  for i in 1 2 3

  do

  echo $i

  done

  对test.sh进行普通调式,具体如下所示:

  [root@qfedu ~]# sh -x test.sh

  + for i in 1 2 3

  + echo 1

  1

  + for i in 1 2 3

  + echo 2

  2

  + for i in 1 2 3

  + echo 3

  3

  进入调试模式后,Shell依次执行读入的语句,产生的输出中有的带加号,有的不带,带加号表示该条语句是Shell执行的,不带加号表示该语句是Shell产生的输出。

  3. 中断调试

  在程序中添加一个睡眠,保证有时间进行中断调试 ,若test.sh文件内容如下:

  #!/bin/bash

  for i in 1 2 3

  do

  echo $i

  sleep 3

  done

  在终端下对test.sh进行中断调试,具体如下所示:

  [root@qfedu ~]# ./test.sh

  1

  ^Z

  [1]+ Stopped ./test.sh

  [root@qfedu ~]# fg

  ./test.sh

  2

  3

  在调试过程中,按Ctrl + Z键中断调试,然后再输入fg并回车,继续调试。

  4. bashdb调试工具

  bashdb调试工具可以完成对Shell脚本的断点设置、单步执行、变量观察等许多操作。该工具默认未安装,使用前需要下载并安装,具体如下所示。

  (1)下载安装包,下载地址为https://sourceforge.net/projects/bashdb/files/bashdb/,根据bash版本选择合适的安装包,此处下载后的文件名为bashdb-4.4-0.92.tar.gz。

  (2)将安装包解压到/usr/src目录下,并进入该目录,具体如下所示:

  [root@qfedu ~]# tar -zxvf bashdb-4.4-0.92.tar.gz -C /usr/src

  [root@qfedu ~]# cd /usr/src/bashdb-4.4-0.92

  (3)安装bashdb,具体如下所示:

  [root@qfedu bashdb-4.4-0.92]# ./configure

  [root@qfedu bashdb-4.4-0.92]# make

  [root@qfedu bashdb-4.4-0.92]# make install

  bashdb安装完成后,就可以对Shell脚本进行调试。

  若test.sh文件内容如下:

  #!/bin/bash

  echo "程序开始!"

  for i in 1 2 3

  do

  echo "第$i次循环开始!"

  echo $i

  echo "第$i次循环开始!"

  done

  echo "程序结束!"在终端下输入以下命令:

  [root@qfedu bashdb-4.4-0.92]# ./bashdb --debugger /root/test.sh

  bash debugger, bashdb, release 4.4-0.92

  Copyright 2002, 2003, 2004, 2006-2012, 2014, 2016 Rocky Bernstein

  This is free software, covered by the GNU General Public License, and you are

  welcome to change it and/or distribute copies of it under certain conditions.

  (/root/test.sh:2):

  2: echo "程序开始!"

  bashdb<0> n #执行下一条语句

  程序开始!

  (/root/test.sh:3):

  3: for i in 1 2 3

  bashdb<1> l #列出当前行的上下行

  1: #!/bin/bash

  2: echo "程序开始!"

  3: => for i in 1 2 3

  4: do

  5: echo "第$i次循环开始!"

  6: echo $i

  7: echo "第$i次循环开始!"

  8: done

  9: echo "程序结束!"

  bashdb<2> b 6 #在行号为6的行设置断点

  Breakpoint 1 set in file /root/test.sh, line 6.

  bashdb<3> c #继续运行到断点处

  第1次循环开始!

  Breakpoint 1 hit (1 times).

  (/root/test.sh:6):

  6: echo $i

  bashdb<4> print $i #打印变量值

  1

  bashdb<5> c

  1

  第1次循环开始!

  第2次循环开始!

  Breakpoint 1 hit (2 times).

  (/root/test.sh:6):

  6: echo $i

  bashdb<6> print $i

  2

  bashdb<7> finish #执行完一个函数或一个循环

  2

  第2次循环开始!

  第3次循环开始!

  Breakpoint 1 hit (3 times).

  (/root/test.sh:6):

  6: echo $i

  bashdb<8> print $i

  3

  bashdb<9> finish

  3

  第3次循环开始!

  程序结束!

  (/usr/src/bashdb-4.4-0.92/bashdb:1):

  1: #!/usr/bin/bash

  bashdb<10> q #退出

  bashdb: That's all, folks...

  以上就是bashdb调试时常用的命令,其他命令可以在调试时输入help来获取详细说明。

  2.10 本章小结

  本章主要介绍了Shell编程相关的知识,包括变量、字符串、数组、运算符、流程控制、函数、调试。学习完本章知识,应该能够编写并调试简单的Shell脚本,为以后使用Shell编程打下基础。

  2.11 习题

  1.填空题

  (1) Shell既是一种命令语言,又是一种 语言。

  (2) 若需要访问变量,则在变量名前必须添加 符号。

  (3) 只读变量的关键字是 。

  (4) 在Shell中,数组分为普通数组和 数组。

  (5) 循环语句分为for循环语句、while循环语句和 循环语句。

  2.选择题

  (1) 删除变量的命令是( )。

  A.unset B.remove

  C.delete D.rm

  (2) ( )用于显示函数调用结束时的退出状态。

  A.$* B.$?

  C.$@ D.$0

  (3) ( )语句不能用于循环控制流程。

  A.for B.go

  C.while D.until

  (4) ( )运算符用于检测两个字符串是否相等。

  A.!= B.-z

  C.= D.-n

  (5) ( )语句用于强行退出当前循环。

  A.quit B.break

  C.exit D.continue

  3.思考题

  (1) 字符串表示有几种形式,区别是什么?

  (2) 文件包含有几种形式,分别是什么?

上一篇:HTML5工具初识之网页编辑器

下一篇:第 3 章 认识Hadoop

QQ技术交流群

千锋IT培训视频教程群
724707829

加入群聊

视频推荐

MORE > >