shell编程之函数与数组和免交互

149 阅读2分钟

一.shell编程之函数

在编写脚本时,有些脚本可以反复使用,可以调用函数来解决。

语句块定义成函数约等于别名。

1.函数的作用:

  1. 使用函数可以避免代码重复;
  2. 使用函数可以将一个大的工程分割为若干小的功能模块,代码的可读性更强。

2.函数的使用方法:

  1. 先定义函数
  2. 再引用函数

3.shell中定义函数有两种格式:

格式1:

[ function ] 函数名 () { 命令序列

[ return x ] #使用return或者exit可以显式的结束函数

}

格式2:

函数名 (){

命令序列

}

举例1

微信截图_20230815184459.png

举例2

微信截图_20230815185225.png

微信截图_20230815185340.png

4.删除函数unset

微信截图_20230815184712.png

5.查看函数declare

微信截图_20230815185653.png

6.函数返回值

获得函数返回值的两种方式:

  1. return表示退出函数并返回一个退出值,脚本中可以用$?变量显示该值。
  2. 在函数体中用 echo 输出返回值。并在函数体外使用变量赋值后,可再进一步对函数的返回值进行加工操作。

举例1:

微信截图_20230815190939.png

微信截图_20230815190958.png

举例2:

微信截图_20230815191658.png

微信截图_20230815191718.png

7.函数传参

在Shell中,调用函数时可以向其传递参数。

在函数体内部,通过 n的形式来获取参数的值,例如,n的形式来获取参数的值,例如,1表示第一个参数,$2表示第二个参数…即使用位置参数来实现参数传递。

举例:

微信截图_20230815193248.png

微信截图_20230815193310.png

8.函数变量的作用范围

函数变量的作用范围

  • 函数在shell脚本中仅在当前shell环境中有效
  • shell脚本中变量默认全局有效
  • 将变量限定在函数内部使用local命令

举例1:

微信截图_20230816161726.png

微信截图_20230816161954.png

举例2:将变量限定在函数内部使用local命令

微信截图_20230816162651.png

微信截图_20230816162611.png

9.函数的递归

调用自己本身

示例:求任意数字的阶乘

微信截图_20230816170145.png

微信截图_20230816170220.png

二.shell编程之数组

1.shell数组的定义

  • 数组中可以存放多个值。Bash Shell 只支持一维数组(不支持多维数组)

数组元素的下标由 0 开始。

  • Shell 数组用括号来表示,元素用"空格"符号分割开

在shell语句中,使用、遍历数组的时候,数组格式要写成 arr[@]{arr[@]} 或 {arr[*]}

2.定义数组的方法

Shell中,数组用括号来表示,元素用"空格"符号分隔开。

数组包括的数据类型:

  • 数值型
  • 字符型 (如果元素值为字符类型,需要加单引号或双引号,防止单个元素中有空格被当成2个元素)
  • 混合型数值+字符

方法1:

数组名=(value1 value2 value3 value4 ...)

微信截图_20230816170755.png

方法2

列表名="value1 value2 value3 value4 value5"  

数组名=($列表名)

微信截图_20230816170947.png

方法3

微信截图_20230816171315.png

方法4

数组名[0]=value1

数组名[1]=value2  

数组名[2]=value3  

数组名[3]=value4

微信截图_20230816171553.png

3.数组遍历

微信截图_20230816172158.png

4.数组切片

格式:${数组名[@/*]:其实位置:长度}

微信截图_20230816172755.png

5.数组替换

格式:${数组名[@/*]:/查找字符/替换字符}

微信截图_20230816173349.png

微信截图_20230816173552.png

6.数组删除和指定下标的值删除

微信截图_20230816173753.png

微信截图_20230816174005.png

7.查看所有数组

微信截图_20230816182835.png

三.shell编程之免交互

1.Here Document免交互

免交互定义

  • 使用I/O重定向的方式将命令列表提供给交互式程序
  • 标准输入的一种替代品

格式:

命令 <<标记

...

...

标记

使用注意项:

  • 标记可以使用任意合法字符但开头标记与结尾标记需要保持一致
  • 结尾的标记一定要定格写,前面不能有任何字符
  • 结尾的标记后面也不能有任何字符(包括空行)
  • 开头标记前后的空格会被省略掉

举例1:统计输入行

微信截图_20230816184352.png

举例2:改密

微信截图_20230816184639.png

举例3:重定向导入文件

微信截图_20230816184929.png

2.Here Document变量设定

Here Document也支持变量的使用如果标记之间有变量被使用,会先替换变量值。如果想要将一些内容写入文件,除了常规的方法外,也可以使用 Here Document。如果写入 的内容中包含变量,在写入文件时要先将变量替换成实际值,在结合 cat 命令完成写入。

举例:

微信截图_20230816190253.png

3.expect

expect 定义

  • 是建立在tcl(tool command language)语言基础上的一个工具,常被用于进行自动化控制和测试,解决shell脚本中交互的相关问题

注:expect需要额外安装

expect安装

rpm -q expect rpm -q tcl yum install -y expect

expect基本命令

3.1脚本解释器

  • expect脚本中首先引入文件,表明使用的是哪一个shell
  • #!/usr/bin/expect

3.2spawn 启动进程并捕捉交互信息

  • spawn后面通常跟一-个Linux执行命令,表示开启一个会话、启动进程,并跟踪后续交互信息
  • 例如:spawn passwd root

3.3expect 从进程接收字符串

  • 判断上次输出结果中是否包含指定的字符串,如果有则立即返回,否则就等待超时时间后返回;
  • 只能捕捉由spawn启动的进程的输出;
  • 用于接收命令执行后的输出,然后和期望的字符串匹配

3.4send 用于向进程发送字符串

  • 向进程发送字符串,用于模拟用户的输入;
  • 该命令不能自动回车换行,一般要加\r (回车)或者\n

结束符

3.5expect eof

  • 表示交互结束,等待执行结束,退回到原用户,与spawn对应。
  • 比如切换到root用户,expect脚本默认的是等待10s当执行完命令后,默认停留10s后,自动切回了原用户

3.6interact

  • 执行完后保持交互状态,把控制权交给控制台会停留在目标终端而不会退回到原终端,这个时候就可以手工操作了,interact后的命.令不起作用;
  • 比如interact后添加exit,并不会退出root用户。而如果没有interact则登录完成后会退出,而不是留在远程终端上。
  • 使用interact会保持在终端而不会退回到原终端;比如切换到root用户,会一直在root用户状态下:比如ssh到另外一台服务器,会一直在目标服务器终端,而不会切换到原来服务器

注意expect eof 与interact只能二选一

set

  • expect 默认的超时时间是10秒,通过set 命令可以设置会话超时时间,若不限制超时时间则应设置为-1

例子: set time out 30

3.7send_users

  • 表示回显命令与echo相同

3.8接收参数

  • expect 脚本可以接受从bash命令行传递参数,使用 [lindex $argv n]获得。其中你从0开始,分别表示第一个,第二个,第三个.....参数

注:注意:expect脚本不能通过bash、source. 来执行(因为这三种方式是调用shell解释器),只能通过绝对路径或相对路径来执行