Shell 编程从入门到精通 - 第 03 章
发表于:2025-02-13 作者:千家信息网编辑
千家信息网最后更新 2025年02月13日,Shell 编程的基本元素编程语言变量类型:变量对于编程语言来说很重要,编程语言使用变量来存储数据,执行运输。静态类型语言:一种在编译期间就确定数据类型的语言。大多数是通过在使用任一变量之前声明其数据
千家信息网最后更新 2025年02月13日Shell 编程从入门到精通 - 第 03 章Shell 编程的基本元素
编程语言变量类型:变量对于编程语言来说很重要,编程语言使用变量来存储数据,执行运输。
静态类型语言:一种在编译期间就确定数据类型的语言。大多数是通过在使用任一变量之前声明其数据类型来保证这一点,例如 JAVA 和 C。
动态类型语言:一种在运行期间才去确定数据类型的语言。它确定一个变量的类型是在第一次给变量赋值的时候,例如 VBScript 和 Pthyhon。
强类型语言:一种总是强制类型定义的语言,当有一个整数时,不进行明确转换,不能把它当做一个字符串,例如 JAVA 和 Python。
弱类型语言:一种类型可以被忽略的语言,整数变量可以看做字符串,例如 VBScript 和 Shell。
![](https://www.aqdb.cn/uploadfile/a1/01a04d9e.jpg)
从上图的例子中可以看出,Bash Shell 中的变量是不区分类型的。
shell 中的三种变量,用户变量在编程过程中使用最多,位置变量在对参数判断和命令返回值判断时会使用,环境变量主要是在程序运行的时候需要设置。
用户变量:用户在 shell 编程过程中定义的变量,分为局部变量和全局变量。默认情况下,用户定义的变量都是全局变量,使用 local 限定词定义的才是局部变量。变量定义的语法为 varname=value。等号两边不能有空格,而且变量值多余一个单词的情况下,需要将值用引号括起来。在命令中引用变量值时,需要在变量名前加上 $。
unset varname 可以删除变量,但 shell 在遇到未定义变量时返回错误,因此在正常情况下并不这样使用。
大括号操作符可以使用 shell 字符串操作的更多高级功能,即字符串处理运算符。它可以完成:确保变量存在且有值;设置变量的默认值;捕获未设置变量而导致的错误;删除匹配模式的变量的值部分内容。
上表中每个冒号都是可选的,如果省略冒号,则将每个定义中的"存在且非 null"改为"存在",即变量运算符只判定变量是否存在。
![](https://www.aqdb.cn/uploadfile/c6/84f05e5e.jpg)
模式匹配运算符可以对值进行操作,通常用于切割路径名称或文件名后缀
上图中的变量替换,使用了两种方法,将 PATH 变量中的冒号都替换成了换行符。
再举一个例子,通过模式匹配删除等号(包括等号)之后的所有字符,输出部分就是变量名,删除等号(包括等号)之前的所有字符,输出部分就为变量值。
${#varname}参数返回 varname 值字符串中的字符个数。
除了通过赋值语句与通过用户将变量作为命令行参数给出获取变量值之外,另外一种方法为命令替换。它允许使用命令的标准输出,就像一个变量值一样,语法为 `command`,这里 ` 为反引号,它将命令的输出作为表达式值。
位置变量:也称为系统变量、位置参数,是 shell 脚本运行时传递给脚本的参数,同时也表示在 shll 函数内部的函数参数。它们的名字是以数字命名 $0~$9,如果超过这个范围需要用括号括起来,即 ${10}。
上图中是几个常见的位置变量。其中 $# 输出变量的个数;$? 输出上条命令的返回值;$0 输出命令的名字;$* 输出所有参数,在双引号中使用 \ 进行转义。
上图程序运行过程解释如下:判断运行参数个数,如果不等于 2,显示 Usage 内容,$0 代表的是脚本自身;用 grep 命令在 $2 文件中查找 $1 字符串;判断前一条命令的返回值,成功显示找到的相关信息,不成功则显示 echo 内容;在双引号中要显示引号,需要加上 \ 转义。
shell 中内置了一个 shift 命令,它可以"截去"参数列表中最左端的一个,执行了 shift 后,$1 的值将会丢失,而 $2 的值将会赋给 $1,以此类推。$# 输出结果也会减一。shift 命令默认为 shift 1,即截去一个参数。
上例演示了 shift 的作用,将文件名作为参数传入脚本中,每次读取一个文件。另外也使用了循环的方式来实现此功能。
环境变量:影响当前 shell 进程运行情况的变量。
shell 执行命令的顺序:交互 shell 在获得用户输入时,并不是直接在 PATH 路径中查找,而是按照固定顺序依次查找命令位置。搜索顺序为别名(alias)、关键字(if、for)、函数、内置命令(cd、pwd)、外部命令(脚本或可执行程序,到这里才在 PATH 路径中查找)。
使用函数需要遵循以下的规则:先定义,后使用;允许以给位置参数赋值的方式向函数传递参数,函数体内部可以使用 local 限定词创建局部变量;在函数中使用 exit 命令将退出脚本,使用 return 命令退回到原本调用函数的地方,且 return 命令返回最后一条命令的退出状态;内置命令 export -f 可以将函数导出到子 shell 中;可以使用 source 或 dot 命令将保存在其他文件中的函数装入当前脚本;函数可以进行无限制的递归调用;可以使用 declare -f(-F) 找到登录会话中定义的函数。
函数定义分为上图中的两种形式,二者没有本质上的区别。unset -f funcname 可以删除定义的函数,-f 提示 unset 命令删除的是函数。
首先,通过 source 命令将函数从文件中读入,可以如使用命令一样调用函数,然后将用户名作为参数传入函数中,判断用户是否在线。
参数 $1 和 $2 分别对应于函数的两个位置参数,在函数内部获取位置参数才将它们相加;return 命令返回两个位置参数的和;source 命令读入函数;$? 返回上一条命令的返回结果。
if/else 语句是 shell 内置的最简单的流程控制语句,用于判断当某条件成立时,则执行某些命令,常用于选项不多的情况。
在最简形式(没有 elif 和 else)中,只有当 condition 为真时,才执行 statements 语句;elif 可以有任意多个,它可以选择更多的条件,提供更多的选择,else 语句则当所有的 if 和 elif 的 condition 都为假时才执行。
命令(函数)的退出状态:每一条命令或函数,在退出时都会返回一个小的整数值给调用它的程序。
在 shell 的判断语句中,条件(condition)实际上是语句列表而不是一般的布尔表达式。通常退出状态 0 表示函数或命令执行成功,非 0 数表示失败。
shell 语法允许在逻辑上操作退出状态,常见的有 NOT,AND 和 OR。
NOT 操作符是 !,在 condition 条件判断后,用 ! 取反,再测试选择执行语句。AND 操作符是 &&,先判断 condition1,成功之后再判断 condition2,如果两个都判断成功,则整个判断语句成功。OR 操作符是 ||,只要两个或多个条件中有一个成功,则整个判断语句成功。AND 和 OR 都是短路运算符,即只要判断出整个语句的真假,则直接返回,不向后继续判断,即使后面的语句根本无法执行。
if 语句唯一可以测试的内容是退出状态,不能用于检测表达式的值。但是通过 test 命令或 [...]的语法检测,此时"["后面和"]"前面必须有空格。
shell 支持字符串的比较,结合 test 或[ ... ]命令能判断判断比较结果,然后再进行相关操作。
将第一个位置参数传递给 test.sh,当 $1 不存在时,显示一条出错信息,如果 $1 存在且大于 0,则无显示。-s 参数与文件名之间必须要有一个空格。$1 两边的引号确保即使它为一个空字符串,程序要能正常运行。
如果给出的位置参数小于 2 或 $1 指定的文件不存在,则退出。
上表为常用的关于 test 的参数。
首先,判断文件是否为目录;如果不是目录,则判断文件是否存在;如果文件存在,则判断文件是否具有读写执行的权限,通过则显示 echo 语句;以上所有判定都不通过时,显示 echo 语句。
可以使用逻辑操作符连接带参数的判断语句,也可以使用逻辑操作符将表达式和 shell 命令组合在一起。
case 也是一个流程控制结构,shell 中的 case 语句可以依据可包含通配符的模式测试字符串。通常可以使用 if-elif 语句配合 test 实现同样的功能,但是当选择数目过多时,就会体现出语句太长的局限性。
从语法中可以看出,任何 pattern 之间都可以由 | 分割的几个模式组成,这种情况下 expression 匹配其中任意一个模式则执行相应语句。模式匹配按顺序依次执行,知道匹配上为止,如果无法匹配,则不执行任何操作。
case 语句与 fi 语句一样,结束时是通过字符串颠倒(reverse)。
判断文件后缀,根据不同后缀选择不同的读取方式,最后一个 * 匹配所有其他匹配不上的形式,相当于 C 语言中的 default。
循环可以控制某些代码的重复行为或允许对多个对象操作。
for 循环用于遍历整个对象/数字列表,依次执行每个独立对象/数字的循环内容,在 shell 脚本里,对象可以是命令行参数、文件名或者任何可以以列表格式建立的东西。
list 为名称列表,在 for 循环中对名称列表中的每个对象进行相应操作,可以通过命令/模式匹配等操作来获取名称列表。
两个例子都可以遍历 mp3 文件并且依次播放。但是使用 find 命令会层层深入文件夹依次查找,而直接列出只会包含当前目录的文件夹。执行反单引号(``)之前的命令,引用结果作为字符串。for 循环中如果 in list 参数被省略,则默认为 in "$@",即命令行参数的引用列表。
shell 中的 while 和 until 循环与传统语言中的 while 和 do/until 相似,它们允许代码在某些条件为真(或直到为真)时重复运行。while 与 until 唯一的区别在于如何判断 condition 的退出状态。在 while 语句中当 condition 的退出状态为真时循环继续运行,否则退出循环;而 until 语句中当 condition 的退出状态为真时循环退出,否则继续运行。它们中的 condition,可以是简单的命令/列表,或者是包含 && 或 || 连接的命令,与 if 语句中的 test 一样。
遍历 PATH 路径:先赋值 path;判断当 path 不为空,则使用 ls -ld 列出 path 中的第一个目录;然后截去 path 中的第一个目录和冒号;当 path 被截成空字符串("")时,退出循环。
在 shell 中经常使用 while true 或者 until false 来构建无限循环。continue 语句用于在循环体中提早开始下一轮循环,break 语句用于跳出整个循环,而 continue 与break 语句也弥补了 shell 中没有 goto 的不足。在多层循环中,continue n 表示会把 n 层的剩余代码都去掉,break n 表示退出 n 层循环。
Shell 编程的基本元素
编程语言变量类型:变量对于编程语言来说很重要,编程语言使用变量来存储数据,执行运输。
静态类型语言:一种在编译期间就确定数据类型的语言。大多数是通过在使用任一变量之前声明其数据类型来保证这一点,例如 JAVA 和 C。
动态类型语言:一种在运行期间才去确定数据类型的语言。它确定一个变量的类型是在第一次给变量赋值的时候,例如 VBScript 和 Pthyhon。
强类型语言:一种总是强制类型定义的语言,当有一个整数时,不进行明确转换,不能把它当做一个字符串,例如 JAVA 和 Python。
弱类型语言:一种类型可以被忽略的语言,整数变量可以看做字符串,例如 VBScript 和 Shell。
![](https://www.aqdb.cn/uploadfile/a1/01a04d9e.jpg)
从上图的例子中可以看出,Bash Shell 中的变量是不区分类型的。
shell 中的三种变量,用户变量在编程过程中使用最多,位置变量在对参数判断和命令返回值判断时会使用,环境变量主要是在程序运行的时候需要设置。
用户变量:用户在 shell 编程过程中定义的变量,分为局部变量和全局变量。默认情况下,用户定义的变量都是全局变量,使用 local 限定词定义的才是局部变量。变量定义的语法为 varname=value。等号两边不能有空格,而且变量值多余一个单词的情况下,需要将值用引号括起来。在命令中引用变量值时,需要在变量名前加上 $。
unset varname 可以删除变量,但 shell 在遇到未定义变量时返回错误,因此在正常情况下并不这样使用。
大括号操作符可以使用 shell 字符串操作的更多高级功能,即字符串处理运算符。它可以完成:确保变量存在且有值;设置变量的默认值;捕获未设置变量而导致的错误;删除匹配模式的变量的值部分内容。
上表中每个冒号都是可选的,如果省略冒号,则将每个定义中的"存在且非 null"改为"存在",即变量运算符只判定变量是否存在。
![](https://www.aqdb.cn/uploadfile/c6/84f05e5e.jpg)
模式匹配运算符可以对值进行操作,通常用于切割路径名称或文件名后缀
上图中的变量替换,使用了两种方法,将 PATH 变量中的冒号都替换成了换行符。
再举一个例子,通过模式匹配删除等号(包括等号)之后的所有字符,输出部分就是变量名,删除等号(包括等号)之前的所有字符,输出部分就为变量值。
${#varname}参数返回 varname 值字符串中的字符个数。
除了通过赋值语句与通过用户将变量作为命令行参数给出获取变量值之外,另外一种方法为命令替换。它允许使用命令的标准输出,就像一个变量值一样,语法为 `command`,这里 ` 为反引号,它将命令的输出作为表达式值。
位置变量:也称为系统变量、位置参数,是 shell 脚本运行时传递给脚本的参数,同时也表示在 shll 函数内部的函数参数。它们的名字是以数字命名 $0~$9,如果超过这个范围需要用括号括起来,即 ${10}。
上图中是几个常见的位置变量。其中 $# 输出变量的个数;$? 输出上条命令的返回值;$0 输出命令的名字;$* 输出所有参数,在双引号中使用 \ 进行转义。
上图程序运行过程解释如下:判断运行参数个数,如果不等于 2,显示 Usage 内容,$0 代表的是脚本自身;用 grep 命令在 $2 文件中查找 $1 字符串;判断前一条命令的返回值,成功显示找到的相关信息,不成功则显示 echo 内容;在双引号中要显示引号,需要加上 \ 转义。
shell 中内置了一个 shift 命令,它可以"截去"参数列表中最左端的一个,执行了 shift 后,$1 的值将会丢失,而 $2 的值将会赋给 $1,以此类推。$# 输出结果也会减一。shift 命令默认为 shift 1,即截去一个参数。
上例演示了 shift 的作用,将文件名作为参数传入脚本中,每次读取一个文件。另外也使用了循环的方式来实现此功能。
环境变量:影响当前 shell 进程运行情况的变量。
shell 执行命令的顺序:交互 shell 在获得用户输入时,并不是直接在 PATH 路径中查找,而是按照固定顺序依次查找命令位置。搜索顺序为别名(alias)、关键字(if、for)、函数、内置命令(cd、pwd)、外部命令(脚本或可执行程序,到这里才在 PATH 路径中查找)。
使用函数需要遵循以下的规则:先定义,后使用;允许以给位置参数赋值的方式向函数传递参数,函数体内部可以使用 local 限定词创建局部变量;在函数中使用 exit 命令将退出脚本,使用 return 命令退回到原本调用函数的地方,且 return 命令返回最后一条命令的退出状态;内置命令 export -f 可以将函数导出到子 shell 中;可以使用 source 或 dot 命令将保存在其他文件中的函数装入当前脚本;函数可以进行无限制的递归调用;可以使用 declare -f(-F) 找到登录会话中定义的函数。
函数定义分为上图中的两种形式,二者没有本质上的区别。unset -f funcname 可以删除定义的函数,-f 提示 unset 命令删除的是函数。
首先,通过 source 命令将函数从文件中读入,可以如使用命令一样调用函数,然后将用户名作为参数传入函数中,判断用户是否在线。
参数 $1 和 $2 分别对应于函数的两个位置参数,在函数内部获取位置参数才将它们相加;return 命令返回两个位置参数的和;source 命令读入函数;$? 返回上一条命令的返回结果。
if/else 语句是 shell 内置的最简单的流程控制语句,用于判断当某条件成立时,则执行某些命令,常用于选项不多的情况。
在最简形式(没有 elif 和 else)中,只有当 condition 为真时,才执行 statements 语句;elif 可以有任意多个,它可以选择更多的条件,提供更多的选择,else 语句则当所有的 if 和 elif 的 condition 都为假时才执行。
命令(函数)的退出状态:每一条命令或函数,在退出时都会返回一个小的整数值给调用它的程序。
在 shell 的判断语句中,条件(condition)实际上是语句列表而不是一般的布尔表达式。通常退出状态 0 表示函数或命令执行成功,非 0 数表示失败。
shell 语法允许在逻辑上操作退出状态,常见的有 NOT,AND 和 OR。
NOT 操作符是 !,在 condition 条件判断后,用 ! 取反,再测试选择执行语句。AND 操作符是 &&,先判断 condition1,成功之后再判断 condition2,如果两个都判断成功,则整个判断语句成功。OR 操作符是 ||,只要两个或多个条件中有一个成功,则整个判断语句成功。AND 和 OR 都是短路运算符,即只要判断出整个语句的真假,则直接返回,不向后继续判断,即使后面的语句根本无法执行。
if 语句唯一可以测试的内容是退出状态,不能用于检测表达式的值。但是通过 test 命令或 [...]的语法检测,此时"["后面和"]"前面必须有空格。
shell 支持字符串的比较,结合 test 或[ ... ]命令能判断判断比较结果,然后再进行相关操作。
将第一个位置参数传递给 test.sh,当 $1 不存在时,显示一条出错信息,如果 $1 存在且大于 0,则无显示。-s 参数与文件名之间必须要有一个空格。$1 两边的引号确保即使它为一个空字符串,程序要能正常运行。
如果给出的位置参数小于 2 或 $1 指定的文件不存在,则退出。
上表为常用的关于 test 的参数。
首先,判断文件是否为目录;如果不是目录,则判断文件是否存在;如果文件存在,则判断文件是否具有读写执行的权限,通过则显示 echo 语句;以上所有判定都不通过时,显示 echo 语句。
可以使用逻辑操作符连接带参数的判断语句,也可以使用逻辑操作符将表达式和 shell 命令组合在一起。
case 也是一个流程控制结构,shell 中的 case 语句可以依据可包含通配符的模式测试字符串。通常可以使用 if-elif 语句配合 test 实现同样的功能,但是当选择数目过多时,就会体现出语句太长的局限性。
从语法中可以看出,任何 pattern 之间都可以由 | 分割的几个模式组成,这种情况下 expression 匹配其中任意一个模式则执行相应语句。模式匹配按顺序依次执行,知道匹配上为止,如果无法匹配,则不执行任何操作。
case 语句与 fi 语句一样,结束时是通过字符串颠倒(reverse)。
判断文件后缀,根据不同后缀选择不同的读取方式,最后一个 * 匹配所有其他匹配不上的形式,相当于 C 语言中的 default。
循环可以控制某些代码的重复行为或允许对多个对象操作。
for 循环用于遍历整个对象/数字列表,依次执行每个独立对象/数字的循环内容,在 shell 脚本里,对象可以是命令行参数、文件名或者任何可以以列表格式建立的东西。
list 为名称列表,在 for 循环中对名称列表中的每个对象进行相应操作,可以通过命令/模式匹配等操作来获取名称列表。
两个例子都可以遍历 mp3 文件并且依次播放。但是使用 find 命令会层层深入文件夹依次查找,而直接列出只会包含当前目录的文件夹。执行反单引号(``)之前的命令,引用结果作为字符串。for 循环中如果 in list 参数被省略,则默认为 in "$@",即命令行参数的引用列表。
shell 中的 while 和 until 循环与传统语言中的 while 和 do/until 相似,它们允许代码在某些条件为真(或直到为真)时重复运行。while 与 until 唯一的区别在于如何判断 condition 的退出状态。在 while 语句中当 condition 的退出状态为真时循环继续运行,否则退出循环;而 until 语句中当 condition 的退出状态为真时循环退出,否则继续运行。它们中的 condition,可以是简单的命令/列表,或者是包含 && 或 || 连接的命令,与 if 语句中的 test 一样。
遍历 PATH 路径:先赋值 path;判断当 path 不为空,则使用 ls -ld 列出 path 中的第一个目录;然后截去 path 中的第一个目录和冒号;当 path 被截成空字符串("")时,退出循环。
在 shell 中经常使用 while true 或者 until false 来构建无限循环。continue 语句用于在循环体中提早开始下一轮循环,break 语句用于跳出整个循环,而 continue 与break 语句也弥补了 shell 中没有 goto 的不足。在多层循环中,continue n 表示会把 n 层的剩余代码都去掉,break n 表示退出 n 层循环。
命令
变量
语句
参数
函数
文件
循环
字符
语言
类型
位置
字符串
运行
输出
成功
模式
状态
用户
脚本
引号
数据库的安全要保护哪些东西
数据库安全各自的含义是什么
生产安全数据库录入
数据库的安全性及管理
数据库安全策略包含哪些
海淀数据库安全审计系统
建立农村房屋安全信息数据库
易用的数据库客户端支持安全管理
连接数据库失败ssl安全错误
数据库的锁怎样保障安全
电力网络安全防护的原则
新软件开发可能出现的问题
LICHUAN服务器
无法接受服务器什么意思
次时代服务器怎么样
数据库画像
审计局网络安全工作管理制度
软件开发培训机构郑州
目前的关系型数据库
软件开发工作室平台
数据库electric
邮政集团软件开发待遇
计算机软件开发工资一个月多少钱
mc饥饿游戏服务器
广州俊荣网络技术有限公司
僵尸毁灭工程要搭服务器吗
质量可靠的软件开发外包
网络安全内容的四个方面
怀化网络安全系统生产厂家
山东移动公司做软件开发
mc的服务器是被迷你玩家炸的吗
广西企业中台数据库
服务器绑定
sol数据库教程
药店配送网络技术
服务器密码信封管理
图形+管理服务器
国家网络安全中心属于哪个部门
服务器挂淘宝主账号怎么弄
学案设计软件开发