38.第六章 Shell脚本编程高级进阶(三)

6.其它脚本相关工具

6.1 信号捕捉 trap

trap 命令可以捕捉信号,修改信号原来的功能,实现自定义功能

#进程收到系统发出的指定信号后,将执行自定义指令,而不会执行原操作
trap '触发指令' 信号

#忽略信号的操作
trap '' 信号

#恢复原信号的操作
trap '-' 信号

#列出自定义信号操作
trap -p

#当脚本退出时,执行finish函数
trap finish EXIT

范例:

[root@rocky8 ~]# kill -L
 1) SIGHUP	 2) SIGINT	 3) SIGQUIT	 4) SIGILL	 5) SIGTRAP
 6) SIGABRT	 7) SIGBUS	 8) SIGFPE	 9) SIGKILL	10) SIGUSR1
11) SIGSEGV	12) SIGUSR2	13) SIGPIPE	14) SIGALRM	15) SIGTERM
16) SIGSTKFLT	17) SIGCHLD	18) SIGCONT	19) SIGSTOP	20) SIGTSTP
21) SIGTTIN	22) SIGTTOU	23) SIGURG	24) SIGXCPU	25) SIGXFSZ
26) SIGVTALRM	27) SIGPROF	28) SIGWINCH	29) SIGIO	30) SIGPWR
31) SIGSYS	34) SIGRTMIN	35) SIGRTMIN+1	36) SIGRTMIN+2	37) SIGRTMIN+3
38) SIGRTMIN+4	39) SIGRTMIN+5	40) SIGRTMIN+6	41) SIGRTMIN+7	42) SIGRTMIN+8
43) SIGRTMIN+9	44) SIGRTMIN+10	45) SIGRTMIN+11	46) SIGRTMIN+12	47) SIGRTMIN+13
48) SIGRTMIN+14	49) SIGRTMIN+15	50) SIGRTMAX-14	51) SIGRTMAX-13	52) SIGRTMAX-12
53) SIGRTMAX-11	54) SIGRTMAX-10	55) SIGRTMAX-9	56) SIGRTMAX-8	57) SIGRTMAX-7
58) SIGRTMAX-6	59) SIGRTMAX-5	60) SIGRTMAX-4	61) SIGRTMAX-3	62) SIGRTMAX-2
63) SIGRTMAX-1	64) SIGRTMAX	

[root@rocky8 ~]# trap -l
 1) SIGHUP	 2) SIGINT	 3) SIGQUIT	 4) SIGILL	 5) SIGTRAP
 6) SIGABRT	 7) SIGBUS	 8) SIGFPE	 9) SIGKILL	10) SIGUSR1
11) SIGSEGV	12) SIGUSR2	13) SIGPIPE	14) SIGALRM	15) SIGTERM
16) SIGSTKFLT	17) SIGCHLD	18) SIGCONT	19) SIGSTOP	20) SIGTSTP
21) SIGTTIN	22) SIGTTOU	23) SIGURG	24) SIGXCPU	25) SIGXFSZ
26) SIGVTALRM	27) SIGPROF	28) SIGWINCH	29) SIGIO	30) SIGPWR
31) SIGSYS	34) SIGRTMIN	35) SIGRTMIN+1	36) SIGRTMIN+2	37) SIGRTMIN+3
38) SIGRTMIN+4	39) SIGRTMIN+5	40) SIGRTMIN+6	41) SIGRTMIN+7	42) SIGRTMIN+8
43) SIGRTMIN+9	44) SIGRTMIN+10	45) SIGRTMIN+11	46) SIGRTMIN+12	47) SIGRTMIN+13
48) SIGRTMIN+14	49) SIGRTMIN+15	50) SIGRTMAX-14	51) SIGRTMAX-13	52) SIGRTMAX-12
53) SIGRTMAX-11	54) SIGRTMAX-10	55) SIGRTMAX-9	56) SIGRTMAX-8	57) SIGRTMAX-7
58) SIGRTMAX-6	59) SIGRTMAX-5	60) SIGRTMAX-4	61) SIGRTMAX-3	62) SIGRTMAX-2
63) SIGRTMAX-1	64) SIGRTMAX	

[root@rocky8 ~]# ping 127.0.0.1
PING 127.0.0.1 (127.0.0.1) 56(84) bytes of data.
64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.050 ms
64 bytes from 127.0.0.1: icmp_seq=2 ttl=64 time=0.029 ms
^C
--- 127.0.0.1 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1054ms
rtt min/avg/max/mdev = 0.029/0.039/0.050/0.012 ms
# 2) SIGINT  相当于ctrl+c 

[root@rocky8 ~]# bc
bc 1.07.1
Copyright 1991-1994, 1997, 1998, 2000, 2004, 2006, 2008, 2012-2017 Free Software Foundation, Inc.
This is free software with ABSOLUTELY NO WARRANTY.
For details type `warranty'. 
^\Quit (core dumped)
#bc支持ctrl+\  退出
# 3) SIGQUIT  相当于ctrl+\

范例:

[root@rocky8 ~]# vim trap.sh
#!/bin/bash
#
#**********************************************************************************************
#Author:        Raymond
#QQ:            88563128
#Date:          2021-10-22
#FileName:      trap.sh
#URL:           raymond.blog.csdn.net
#Description:   The test script
#Copyright (C): 2021 All rights reserved
#*********************************************************************************************
trap 'echo "Press ctrl+c or ctrl+\\"' int quit
trap -p
for ((i+0;i<=10;i++));do
    sleep 1
    echo $i
done
trap '' int
trap -p
for ((i=11;i<=20;i++));do
    sleep 1
    echo $i
done
trap '-' int
trap -p
for ((i=21;i<=30;i++));do
    sleep 1
    echo $i
done

[root@rocky8 ~]# bash trap.sh 
trap -- 'echo "Press ctrl+c or ctrl+\\"' SIGINT
trap -- 'echo "Press ctrl+c or ctrl+\\"' SIGQUIT

1
2
3
^CPress ctrl+c or ctrl+\
4
5
6
^\Quit (core dumped)
Press ctrl+c or ctrl+\
7
8
9
10
trap -- '' SIGINT
trap -- 'echo "Press ctrl+c or ctrl+\\"' SIGQUIT
11
12
13
14
15
16
17
18
19
20
trap -- 'echo "Press ctrl+c or ctrl+\\"' SIGQUIT
21
22
23
24
^C

[root@rocky8 ~]# vim trap_finish.sh
#!/bin/bash
#
#**********************************************************************************************
#Author:        Raymond
#QQ:            88563128
#Date:          2021-10-22
#FileName:      trap_finish.sh
#URL:           raymond.blog.csdn.net
#Description:   The test script
#Copyright (C): 2021 All rights reserved
#*********************************************************************************************
finish(){
    echo finish is at `date +%F_%T` | tee -a /root/finish.log
}

trap finish exit
while true;do
    echo running
    sleep 1
done

[root@rocky8 ~]# bash trap_finish.sh 
running
running
running
^Cfinish is at 2021-10-22_19:03:02

[root@rocky8 ~]# cat finish.log 
finish is at 2021-10-22_19:03:02

6.2 创建临时文件 mktemp

mktemp 命令用于创建并显示临时文件,可避免冲突

格式

mktemp [OPTION]... [TEMPLATE]

说明:TEMPLATE: filenameXXX,X至少要出现三个

常见选项:

-d #创建临时目录
-p DIR或--tmpdir=DIR #指明临时文件所存放目录位置

范例:

[root@rocky8 ~]# mktemp raymondXX
mktemp: too few X's in template ‘raymondXX’
[root@rocky8 ~]# mktemp raymondXXXXX
raymondAGNQF
[root@rocky8 ~]# ls raymondAGNQF 
raymondAGNQF

[root@rocky8 ~]# filename=`mktemp raymondXXXXXX`
[root@rocky8 ~]# echo $filename
raymond5uvfiG

[root@rocky8 ~]#  mktemp -d dirXXX
dirXzt
[root@rocky8 ~]# ls dirXXX
ls: cannot access 'dirXXX': No such file or directory
[root@rocky8 ~]# ll -d dirXzt/
drwx------ 2 root root 6 Oct 22 15:12 dirXzt/

[root@rocky8 ~]# mktemp -p /data testXXX.txt
/data/testy74.txt
[root@rocky8 ~]# ls /data/testy74.txt 
/data/testy74.txt

范例:

[root@rocky8 ~]# vim rm.sh
#!/bin/bash
#
#**********************************************************************************************
#Author:        Raymond
#QQ:            88563128
#Date:          2021-10-22
#FileName:      rm.sh
#URL:           raymond.blog.csdn.net
#Description:   The test script
#Copyright (C): 2021 All rights reserved
#*********************************************************************************************
DIR=`mktemp -d /tmp/trash-$(date +%F_%H-%M-%S)XXXXXX`
mv $* $DIR
echo $* is move tu $DIR

[root@rocky8 ~]# alias rm='~/rm.sh'
[root@rocky8 ~]# chmod +x rm.sh 
[root@rocky8 ~]# rm finish.log
finish.log is move tu /tmp/trash-2021-10-22_15-16-52VxVPyy
[root@rocky8 ~]# ll /tmp/trash-2021-10-22_15-16-52VxVPyy/
total 4
-rw-r--r-- 1 root root 7 Oct 22 15:07 finish.log

6.3 安装复制文件 install

install 功能相当于 cp,mkdir, chmod,chown,chgrp 等相关工具的集合

install命令格式:

install [OPTION]... [-T] SOURCE DEST 单文件
install [OPTION]... SOURCE... DIRECTORY
install [OPTION]... -t DIRECTORY SOURCE...
install [OPTION]... -d DIRECTORY... #创建空目录

选项:

-m MODE,默认755
-o OWNER
-g GROUP
-d DIRNAME 目录

范例:

[root@rocky8 ~]# install -m 600 -o raymond -g bin anaconda-ks.cfg /data/a.cfg
[root@rocky8 ~]# ll /data/a.cfg 
-rw------- 1 raymond bin 1318 Oct 22 15:24 /data/a.cfg

[root@rocky8 ~]# install -m 700 -o raymond -g daemon -d /data/testdir
[root@rocky8 ~]# ll -d /data/testdir/
drwx------ 2 raymond daemon 6 Oct 22 15:25 /data/testdir/

6.4 交互式转化批处理工具 expect

expect 是由Don Libes基于 Tcl( Tool Command Language )语言开发的,主要应用于自动化交互式操作的场景,借助 expect 处理交互的命令,可以将交互过程如:ssh登录,ftp登录等写在一个脚本上,使之自动化完成。尤其适用于需要对多台服务器执行相同操作的环境中,可以大大提高系统管理人员的工作效率

expect 语法:

expect [选项] [ -c cmds ] [ [ -[f|b] ] cmdfile ] [ args ]

常见选项:

-c:从命令行执行expect脚本,默认expect是交互地执行的
-d:可以输出输出调试信息

expect中相关命令

  • spawn 启动新的进程
  • expect 从进程接收字符串
  • send 用于向进程发送字符串
  • interact 允许用户交互
  • exp_continue 匹配多个字符串在执行动作后加此命令

expect最常用的语法(tcl语言:模式-动作)

单一分支模式语法:

[root@rocky8 ~]# expect
-bash: expect: command not found
[root@rocky8 ~]# dnf -y install expect

[root@rocky8 ~]# expect
expect1.1> expect "hi" {send "You said hi\n"}
hahahixixi
You said hi
expect1.2> exit

匹配到hi后,会输出“you said hi”,并换行

多分支模式语法:

[root@rocky8 ~]# expect
expect1.1> expect "hi" { send "You said hi\n" } "hehe" { send "Hehe yourself\n" } "bye" { send "Good bye\n" }
hehe
Hehe yourself
expect1.2> expect "hi" { send "You said hi\n" } "hehe" { send "Hehe yourself\n" } "bye" { send "Good bye\n" }
bye
Good bye
expect1.3> expect "hi" { send "You said hi\n" } "hehe" { send "Hehe yourself\n" } "bye" { send "Good bye\n" }
hi
You said hi
expect1.4> exit

匹配hi,hello,bye任意字符串时,执行相应输出。等同如下:

expect {
    "hi" { send "You said hi\n"}
    "hehe" { send "Hehe yourself\n"}
    "bye" { send " Good bye\n"}
}

[root@rocky8 ~]# expect 
expect1.1> expect {
+> "hi" { send "You said hi\n"}
+> "hehe" { send "Hehe yourself\n"}
+> "bye" { send " Good bye\n"}
+> }
bye
 Good bye
expect1.2> exit

范例1:

[root@rocky8 ~]# vim expect1
#!/usr/bin/expect
spawn scp /etc/fstab 172.31.0.7:/data
expect {
    "yes/no" { send "yes\n";exp_continue }
    "password" { send "123456\n" }
}
expect eof

[root@rocky8 ~]# chmod +x expect1 
[root@rocky8 ~]# ./expect1 
spawn scp /etc/fstab 172.31.0.7:/data
The authenticity of host '172.31.0.7 (172.31.0.7)' can't be established.
ECDSA key fingerprint is SHA256:zb/8mo/ptS0h8eHVY1FDRuvh6aQj1opzpsD7khnYjSo.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '172.31.0.7' (ECDSA) to the list of known hosts.
root@172.31.0.7's password: 
fstab                                                                                                        100%  808   461.5KB/s   00:00    
[root@centos7 ~]# ll /data
total 4
-rw-r--r-- 1 root root 808 Oct 22 15:44 fstab

范例2:expect 变量

[root@rocky8 ~]# vim expect2
#!/usr/bin/expect
set ip 172.31.0.7
set user root
set password 123456
set timeout 10
spawn ssh $user@$ip                                                                                                              
expect {
    "yes/no" { send "yes\n";exp_continue }
    "password" { send "$password\n" }
}
interact

[root@rocky8 ~]# chmod +x expect2
[root@rocky8 ~]# ./expect2
spawn ssh root@172.31.0.7
root@172.31.0.7's password: 
Last login: Fri Oct 22 14:01:56 2021 from 172.31.0.1

[root@centos7 ~]# pwd
/root
[root@centos7 ~]# exit
logout
Connection to 172.31.0.7 closed.

范例3:expect 位置参数

[root@rocky8 ~]# vim expect3
#!/usr/bin/expect
set ip [lindex $argv 0]
set user [lindex $argv 1]
set password [lindex $argv 2]
set timeout 10
spawn ssh $user@$ip
expect {
    "yes/no" { send "yes\n";exp_continue }
    "password" { send "$password\n" }
}
interact

[root@rocky8 ~]# chmod +x expect3

[root@rocky8 ~]# ./expect3 172.31.0.6 root 123456
spawn ssh root@172.31.0.6
root@172.31.0.6's password: 
Last login: Fri Oct 22 14:02:02 2021 from 172.31.0.1
[root@centos6 ~]# exit
logout
Connection to 172.31.0.6 closed.

范例4:shell脚本调用 expect

[root@rocky8 ~]# vim expect4.sh
#!/bin/bash
#
#**********************************************************************************************
#Author:        Raymond
#QQ:            88563128
#Date:          2021-10-22
#FileName:      expect4.sh
#URL:           raymond.blog.csdn.net
#Description:   The test script
#Copyright (C): 2021 All rights reserved
#*********************************************************************************************
ip=$1
user=$2
password=$3
expect <<EOF
set timeout 20
spawn ssh $user@$ip
expect {
    "yes/no" { send "yes\n";exp_continue }
    "password" { send "$password\n" }     
}
expect "]#" { send "useradd hehe\n" }
expect "]#" { send "echo 123456|passwd --stdin hehe\n" }
expect "]#" { send "exit\n" }

[root@rocky8 ~]# chmod +x expect1.sh 
[root@rocky8 ~]# ./expect1.sh 172.31.0.7 root 123456
./expect1.sh: line 24: warning: here-document at line 15 delimited by end-of-file (wanted `EOF')
spawn ssh root@172.31.0.7
root@172.31.0.7's password: 
Last login: Fri Oct 22 15:46:24 2021 from 172.31.1.8
[root@centos7 ~]# useradd hehe
[root@centos7 ~]# echo 123456|passwd --stdin hehe
Changing password for user hehe.
passwd: all authentication tokens updated successfully.
[root@centos7 ~]# [root@rocky8 ~]# 

[root@centos7 ~]# id hehe
uid=1001(hehe) gid=1001(hehe) groups=1001(hehe)

范例5:

[root@rocky8 ~]# vim expect5.sh
#!/bin/bash
#
#**********************************************************************************************
#Author:        Raymond
#QQ:            88563128
#Date:          2021-10-22
#FileName:      expect5.sh
#URL:           raymond.blog.csdn.net
#Description:   The test script
#Copyright (C): 2021 All rights reserved
#*********************************************************************************************
NET=172.31.0
user=root
password=123456

for ID in 6 7;do
ip=$NET.$ID

expect <<EOF
set timeout 20
spawn ssh $user@$ip
expect {
    "yes/no" { send "yes\n";exp_continue }
    "password" { send "$password\n" }     
}
expect "]#" { send "sed -i 's/^SELINUX=enforcing/SELINUX=disabled/' /etc/selinux/config\n" } 
expect "]#" { send "setenforce 0\n" }
expect "]#" { send "exit\n" }
expect eof
EOF
done

[root@rocky8 ~]# chmod +x expect5.sh 
[root@rocky8 ~]# bash expect5.sh
spawn ssh root@172.31.0.6
root@172.31.0.6's password: 
Last login: Fri Oct 22 16:07:11 2021 from 172.31.1.8
[root@centos6 ~]# sed -i 's/^SELINUX=enforcing/SELINUX=disabled/' /etc/selinux/config
[root@centos6 ~]# setenforce 0
setenforce: SELinux is disabled
[root@centos6 ~]# exit
logout
Connection to 172.31.0.6 closed.
spawn ssh root@172.31.0.7
root@172.31.0.7's password: 
Last login: Fri Oct 22 16:07:11 2021 from 172.31.1.8
[root@centos7 ~]# sed -i 's/^SELINUX=enforcing/SELINUX=disabled/' /etc/selinux/config
[root@centos7 ~]# setenforce 0
setenforce: SELinux is disabled
[root@centos7 ~]# exit
logout
Connection to 172.31.0.7 closed.

范例6:shell脚本利用循环调用expect在CentOS和Ubuntu上批量创建用户

[root@rocky8 ~]# vim expect6.sh
#!/bin/bash
#
#**********************************************************************************************
#Author:        Raymond
#QQ:            88563128
#Date:          2021-10-22
#FileName:      expect6.sh
#URL:           raymond.blog.csdn.net
#Description:   The test script
#Copyright (C): 2021 All rights reserved
#*********************************************************************************************
NET=172.31.0
user=root
password=123456
for ID in 6 7;do
ip=$NET.$ID
expect <<EOF
set timeout 20
spawn ssh $user@$ip
expect {
"yes/no" { send "yes\n";exp_continue }
"password" { send "$password\n" }
}
expect "#" { send "useradd test\n" }
expect "#" { send "exit\n" }
expect eof
EOF
done

[root@rocky8 ~]# bash expect6.sh 
spawn ssh root@172.31.0.6
root@172.31.0.6's password: 
Last login: Fri Oct 22 16:06:48 2021 from 172.31.1.8
[root@centos6 ~]# useradd test
[root@centos6 ~]# exit
logout
Connection to 172.31.0.6 closed.
spawn ssh root@172.31.0.7
root@172.31.0.7's password: 
Last login: Fri Oct 22 16:06:47 2021 from 172.31.1.8
[root@centos7 ~]# useradd test
[root@centos7 ~]# exit
logout
Connection to 172.31.0.7 closed.

7.数组 array

7.1 数组介绍

变量:存储单个元素的内存空间

数组:存储多个元素的连续的内存空间,相当于多个变量的集合

数组名和索引(下标)

  • 索引的编号从0开始,属于数值索引
  • 索引可支持使用自定义的格式,而不仅是数值格式,即为关联索引,bash4.0版本之后开始支持
  • bash的数组支持稀疏格式(索引不连续)

7.2 声明数组

#普通数组可以不事先声明,直接使用
declare -a ARRAY_NAME
#关联数组必须先声明,再使用
declare -A ARRAY_NAME

注意:两者不可相互转换

范例:

[root@rocky8 ~]# declare -A course
[root@rocky8 ~]# declare -a course
-bash: declare: course: cannot convert associative to indexed array
[root@rocky8 ~]# file=( *.sh )
[root@rocky8 ~]# declare -A file
-bash: declare: file: cannot convert indexed to associative array

7.3 数组赋值

数组元素的赋值

(1) 一次只赋值一个元素

ARRAY_NAME[INDEX]=VALUE

范例:

[root@rocky8 ~]# name[0]=zhang
[root@rocky8 ~]# name[1]=wang
[root@rocky8 ~]# name[2]=li
[root@rocky8 ~]# echo ${name[0]}
zhang
[root@rocky8 ~]# echo ${name[1]}
wang
[root@rocky8 ~]# echo ${name[2]}
li
[root@rocky8 ~]# echo ${name[*]}
zhang wang li
[root@rocky8 ~]# echo ${name[@]}
zhang wang li

(2) 一次赋值全部元素

ARRAY_NAME=("VAL1" "VAL2" "VAL3" ...)

范例:

[root@rocky8 ~]# title=(ceo cto coo)
[root@rocky8 ~]# echo ${title[@]}
ceo cto coo
[root@rocky8 ~]# echo ${title[*]}
ceo cto coo
[root@rocky8 ~]# echo ${title[2]}
coo

[root@rocky8 ~]# num=({0..9})
[root@rocky8 ~]# echo ${num[0]}
0
[root@rocky8 ~]# echo ${num[1]}
1
[root@rocky8 ~]# echo ${num[3]}
3
[root@rocky8 ~]# echo ${num[*]}
0 1 2 3 4 5 6 7 8 9

[root@rocky8 ~]# touch {a..z}.sh
[root@rocky8 ~]# file=(*.sh)
[root@rocky8 ~]# echo ${file[3]}
d.sh
[root@rocky8 ~]# echo ${file[0]}
a.sh

(3) 只赋值特定元素

ARRAY_NAME=([0]="VAL1" [3]="VAL2" ...)

范例:

[root@rocky8 ~]# student=([0]=zhang [2]=li [3]=zhao) #中间缺失元素,这就叫稀疏格式
[root@rocky8 ~]# echo ${student[*]}
zhang li zhao
[root@rocky8 ~]# echo ${student[0]}
zhang
[root@rocky8 ~]# echo ${student[1]}

[root@rocky8 ~]# echo ${student[2]}
li
[root@rocky8 ~]# echo ${student[3]}
zhao

(4) 交互式数组值对赋值

read -a ARRAY

范例:

[root@rocky8 ~]# read -a student
zhang wang li zhao
[root@rocky8 ~]# echo ${student[@]}
zhang wang li zhao
[root@rocky8 ~]# echo ${student[2]}
li
[root@rocky8 ~]# echo ${#student[*]}
4
[root@rocky8 ~]# student[${#student[*]}]=liu
[root@rocky8 ~]# echo ${student[*]}
zhang wang li zhao liu
[root@rocky8 ~]# student[${#student[*]}]=ma
[root@rocky8 ~]# echo ${student[*]}
zhang wang li zhao liu ma

[root@rocky8 ~]# unset student[1]
[root@rocky8 ~]# echo ${#student[*]}
5
[root@rocky8 ~]# echo ${student[*]}
zhang li zhao liu ma
[root@rocky8 ~]# student[${#student[*]}]=bai
[root@rocky8 ~]# echo ${student[*]}
zhang li zhao liu bai
[root@rocky8 ~]# echo ${student[0]}
zhang
[root@rocky8 ~]# echo ${student[1]}

[root@rocky8 ~]# echo ${student[2]}
li
[root@rocky8 ~]# echo ${student[3]}
zhao
[root@rocky8 ~]# echo ${student[4]}
liu
[root@rocky8 ~]# echo ${student[5]}
bai

[root@rocky8 ~]# student[1]=hou
[root@rocky8 ~]# echo ${student[*]}
zhang hou li zhao liu bai
[root@rocky8 ~]# echo ${student[@]:1:2}
hou li
[root@rocky8 ~]# echo ${student[@]:2}
li zhao liu bai

7.4 显示所有数组

显示所有数组:

declare -a

范例:

[root@rocky8 ~]# declare -a
declare -a BASH_ARGC=()
declare -a BASH_ARGV=()
declare -a BASH_LINENO=()
declare -a BASH_SOURCE=()
declare -ar BASH_VERSINFO=([0]="4" [1]="4" [2]="20" [3]="1" [4]="release" [5]="x86_64-redhat-linux-gnu")
declare -a DIRSTACK=()
declare -a FUNCNAME
declare -a GROUPS=()
declare -a PIPESTATUS=([0]="0")

7.5 引用数组

引用数组元素

${ARRAY_NAME[INDEX]}
#如果省略[INDEX]表示引用下标为0的元素

范例:

[root@rocky8 ~]# declare -a title=([0]="ceo" [1]="coo" [2]="cto")
[root@rocky8 ~]# echo ${title[1]}
coo
[root@rocky8 ~]# echo ${title}
ceo
[root@rocky8 ~]# echo ${title[2]}
cto

引用数组所有元素

${ARRAY_NAME[*]}
${ARRAY_NAME[@]}

范例:

[root@rocky8 ~]# echo ${title[@]}
ceo coo cto
[root@rocky8 ~]# echo ${title[*]}
ceo coo cto

数组的长度,即数组中元素的个数

${#ARRAY_NAME[*]}
${#ARRAY_NAME[@]}

范例:

[root@rocky8 ~]# echo ${#title[*]}
3

7.6 删除数组

删除数组中的某元素,会导致稀疏格式

unset ARRAY[INDEX]

范例:

[root@rocky8 ~]# echo ${title[*]}
ceo coo cto
[root@rocky8 ~]# unset title[1]
[root@rocky8 ~]# echo ${title[*]}
ceo cto

删除整个数组

unset ARRAY

范例:

[root@rocky8 ~]# unset title
[root@rocky8 ~]# echo ${title[*]}

7.7 数组数据处理

数组切片:

${ARRAY[@]:offset:number}
offset #要跳过的元素个数
number #要取出的元素个数
#取偏移量之后的所有元素
{ARRAY[@]:offset}

范例:

[root@rocky8 ~]# num=({0..10})
[root@rocky8 ~]# echo ${num[*]:2:3} #跳过前2个取3个
2 3 4
[root@rocky8 ~]# echo ${num[*]:6} #跳过前6个取后面全部
6 7 8 9 10

向数组中追加元素:

ARRAY[${#ARRAY[*]}]=value
ARRAY[${#ARRAY[@]}]=value

范例:

[root@rocky8 ~]# num[${#num[@]}]=11
[root@rocky8 ~]# echo ${#num[@]}
12
[root@rocky8 ~]# echo ${num[@]}
0 1 2 3 4 5 6 7 8 9 10 11

7.8 关联数组

declare -A ARRAY_NAME
ARRAY_NAME=([idx_name1]='val1' [idx_name2]='val2‘...)

注意:关联数组必须先声明再调用

范例:

[root@rocky8 ~]# emp[ceo]=zhang
[root@rocky8 ~]# emp[cto]=wang
[root@rocky8 ~]# echo ${emp[ceo]}
wang
[root@rocky8 ~]# echo ${emp[cto]}
wang
[root@rocky8 ~]# echo ${emp[*]}
wang
#关联数组,必须先声明再使用

[root@rocky8 ~]# declare -A emp
-bash: declare: emp: cannot convert indexed to associative array
#提示不能转换

[root@rocky8 ~]# unset emp
[root@rocky8 ~]# declare -A emp
[root@rocky8 ~]# emp=([ceo]=zhang [cto]=wang [coo]=li)
[root@rocky8 ~]# echo ${emp[*]}
zhang wang li
[root@rocky8 ~]# echo ${emp[ceo]}
zhang
[root@rocky8 ~]# echo ${emp[cto]}
wang
[root@rocky8 ~]# echo ${emp[coo]}
li

范例:关联数组

[root@rocky8 ~]# declare -A student
[root@rocky8 ~]# student[name1]=lijun
[root@rocky8 ~]# student[name2]=ziqing
[root@rocky8 ~]# student[age1]=18
[root@rocky8 ~]# student[age2]=16
[root@rocky8 ~]# student[gender1]=m
[root@rocky8 ~]# student[city1]=nanjing
[root@rocky8 ~]# student[gender2]=f
[root@rocky8 ~]# student[city2]=anhui
[root@rocky8 ~]# student[gender2]=m
[root@rocky8 ~]# student[name50]=alice
[root@rocky8 ~]# student[name3]=tom
[root@rocky8 ~]# for i in {1..50};do echo student[name$i]=${student[name$i]};done
student[name1]=lijun
student[name2]=ziqing
student[name3]=tom
student[name4]=
student[name5]=
student[name6]=
student[name7]=
student[name8]=
student[name9]=
student[name10]=
student[name11]=
student[name12]=
student[name13]=
student[name14]=
student[name15]=
student[name16]=
student[name17]=
student[name18]=
student[name19]=
student[name20]=
student[name21]=
student[name22]=
student[name23]=
student[name24]=
student[name25]=
student[name26]=
student[name27]=
student[name28]=
student[name29]=
student[name30]=
student[name31]=
student[name32]=
student[name33]=
student[name34]=
student[name35]=
student[name36]=
student[name37]=
student[name38]=
student[name39]=
student[name40]=
student[name41]=
student[name42]=
student[name43]=
student[name44]=
student[name45]=
student[name46]=
student[name47]=
student[name48]=
student[name49]=
student[name50]=alice
上一篇:线性编程14--自动执行excel测试用例


下一篇:Pytest08--数据驱动测试