Linux-Shell编程

Shell编程

一. 执行shell脚本有两种方式:子shell执行和本shell执行

1.1 本shell执行shell脚本的两种方式

  1. 点 加shell文件路径
[root@andy1 ~]# . testshell/shell.sh 
i am shell
  1. source shell文件路径
[root@andy1 ~]# source testshell/shell.sh 
i am shell

1.2 子shell执行shell脚本的两种方式

  1. 路径+shell文件名 这种方式需要shell文件有可执行权限
[root@andy1 ~]# chmod +x testshell/shell.sh 
[root@andy1 ~]# testshell/shell.sh
i am shell
  1. bash shell文件
[root@andy1 ~]# bash testshell/shell.sh 
i am shell

二. login shell和nologin shell

2.1 /etc/profile 和 /etc/bashrc 和 ~/.bash_profile 和 ~/.bashrc 和 ~/.bash_logout 和 ~/.bash_history这六个文件

  1. /etc/profile 和 /etc/bashrc 是系统级别的;
  2. ~/.bash_profile 和 ~/.bashrc 和 ~/.bash_logout 和 ~/.bash_history是用户级别的;
  3. /etc/profile 和 /etc/bashrc 和 ~/.bash_profile 和 ~/.bashrc 是用户登录时执行的;
  4. ~/.bash_logout 和 ~/.bash_history是用户退出时执行的;
  5. /etc/profile 和 ~/.bash_profile是设置环境变量的;
  6. /etc/bashrc 和 ~/.bashrc是设置别名和函数的;
  7. 调用关系:
~/.bash_profile 调用 ~/.bashrc 调用/etc/bashrc 调用 /etc/profile.d/*.sh
		 /etc/profile 调用 /etc/profile.d/*.sh
  1. login shell登录时会执行/etc/profile 和 /etc/bashrc 和 ~/.bash_profile 和 ~/.bashrc这四个文件; nologin shell登录时只会执行 /etc/bashrc 和 ~/.bashrc这两个文件

2.2 用户切换时使用命令su - 用户名 或 su 用户名

  1. su - 用户名 是login shell
  2. su 用户名 是 nologin shell

三. bash shell的特点

3.1 自动补齐

安装bash-completion包
yum -y install bash-completion

3.2 历史命令记忆

!number 执行history中的第几个命令
!string 执行history最后一个以string开头的命令
!! 执行history最后一个命令
!$ 执行history最后一个命令的参数,或前面加上另外的命令来把!$当做这个新命令的参数来执行

[root@master andy]# date
Tue Nov  3 23:17:31 CST 2020
[root@master andy]# !$
date
Tue Nov  3 23:17:38 CST 2020
[root@master andy]# 
[root@master andy]# vi 1.txt
[root@master andy]# !$
1.txt
-bash: 1.txt: command not found
[root@master andy]# 
[root@master andy]# vi 1.txt
[root@master andy]# cat !$
cat 1.txt
我是i.txt
[root@master andy]# 

^R: 手动输入字符串来查找history中的命令来执行

3.3 别名功能

列出系统中所有的别名 alias

[root@master andy]# alias
alias cp='cp -i'
alias egrep='egrep --color=auto'
alias fgrep='fgrep --color=auto'
alias grep='grep --color=auto'
alias l.='ls -d .* --color=auto'

定义一个别名 alias 别名=***

[root@master andy]# alias kang=date
[root@master andy]# kang
Tue Nov  3 23:29:43 CST 2020

删除一个别名定义 unalias 别名

[root@master andy]# unalias ll
[root@master andy]# ll
-bash: ll: command not found
[root@master andy]# 

~用户名 :代码这个用户的家目录

[root@master ~]# cd ~andy
[root@master andy]# pwd
/home/andy

3.4 快捷键

^R:
^D:删除当前字符
^A: 跳到命令头
^E: 跳到命令尾
^L: clear
^U: 删除当前光标以前的所有字符
^K: 删除当前光标右侧所有字符
^S: 锁定终端
^Q: 释放终端

3.5 前后台作业控制

&:后台运行程序
nohup:退出终端后程序仍然运行
^C: 把程序关闭
^Z: 把程序stop到后台

bg num 或 bg %num : 把后台的某个stopped的进程在后台运行起来

[root@master ~]# jobs
[1]   Running                 sleep 1000 &
[2]+  Stopped                 nohup sleep 2000
[3]-  Stopped                 sleep 3000
[root@master ~]# bg %2
[2]+ nohup sleep 2000 &
[root@master ~]# jobs
[1]   Running                 sleep 1000 &
[2]-  Running                 nohup sleep 2000 &
[3]+  Stopped                 sleep 3000
[root@master ~]# 

fg num 或 fg %num : 把后台的某个进程弄回前台并运行

[root@master ~]# jobs
[1]   Running                 sleep 1000 &
[2]-  Running                 nohup sleep 2000 &
[3]+  Stopped                 sleep 3000
[root@master ~]# fg %2
nohup sleep 2000

kill %num: 杀掉某个后台的进程

[root@master ~]# jobs
[1]   Running                 sleep 1000 &
[2]-  Running                 nohup sleep 2000 &
[3]+  Stopped                 sleep 3000
[root@master ~]# kill %3
[root@master ~]# kill %2
[root@master ~]# jobs
[1]   Running                 sleep 1000 &
[2]-  Terminated              nohup sleep 2000
[3]+  Terminated              sleep 3000
[root@master ~]# jobs
[1]+  Running                 sleep 1000 &
[root@master ~]# 

screen:

3.6 输入输出重定向

0:标准输入
1:标准输出
2:标准错误输出
> : 
>> :
2> : 标准错误重定向
2>&1 : 标准错误重定向到标准输出
&> : 标准输出和标准错误输出重定向
cat < /etc/hosts:从文件中重定向到标准输入
cat << EOF: 
cat > file << EOF:
cat << EOF > file:

3.7 管道 | tee

|tee 文件名 :将前面的标准输出写入文件后再输出给标准输出
|tee -a 文件名 :将前面的标准输出追加写入文件后再输出给标准输出

  ifconfig | grep inet |tee 123.txt| grep 192.168.1.224
  ifconfig | grep inet |tee -a 123.txt| grep 192.168.1.224
  df |tee 123.txt | grep '/$'

3.8 shell通配符(元字符)

1. * :匹配任意多个字符
2. ? : 匹配任意一个字符
3. [] : 匹配括号里面任意一个字符  [acdf]   [^0-9]
4. (): 在子shell中执行 (cd / && ll)       (umask 077;touch file01)
5. {}: 集合   touch file{1..9}    mkdir -pv /home/{333/{aaa,bbb},666}
[root@andy1 test]# cp /etc/sysconfig/network-scripts/ifcfg-ens160{,.old}
[root@andy1 test]# ll /etc/sysconfig/network-scripts/ifcfg-ens16*
-rw-r--r--. 1 root root 394 Sep  9 02:12 /etc/sysconfig/network-scripts/ifcfg-ens160
-rw-r--r--. 1 root root 394 Nov  5 19:46 /etc/sysconfig/network-scripts/ifcfg-ens160.old
6. \ : 转义符 让元字符回归本意;让普通字符变成有特殊意义
让元字符回归本意:
echo \*

touch yang\ sheng              空格原本是参数之间的分割,现在用\把空格的这个特殊作用回归了原本的空格,结果创建了一个文件名有空格的文件yang sheng

[root@andy1 ~]# ls /etc/sysconfig/ \
> /etc/hosts \
> /etc/passwd
把回车键转义
[root@andy1 ~]# ll /etc/sysconfig/\
> network\
> -scripts/ifcfg-ens160



让普通字符变成有特殊意义:
echo -e "a\tb"
echo -e "a\nb"

3.9 echo 打印字体的前景颜色和背景颜色

3.9.1 前景颜色

“\e[1;30m” 前景变颜色
“\e[0m” 前景恢复颜色

root@andy1 ~]# echo -e "\e[1;33m我爱你"
我爱你
[root@andy1 ~]# echo -e "\e[1;35m我爱你"
我爱你
[root@andy1 ~]# echo -e "\e[1;36m我爱你"
我爱你
[root@andy1 ~]# echo -e "\e[1;37m我爱你"
我爱你
[root@andy1 ~]# echo -e "\e[1;36m我爱你"
我爱你
[root@andy1 ~]# echo -e "\e[0m"

只变要打印的字的颜色,不改变后续提示的颜色
在这里插入图片描述

3.9.2 背景颜色

“\e[1;40m” 前景变颜色
“\e[0m” 前景恢复颜色
在这里插入图片描述

在这里插入图片描述

四. printf的用法

  1. printf 格式 参数
  2. 例子1

常用的转义字符:

\" - 转义后的双引号
\\ - 转义后的反斜杠
\b - 退格符
\n - 换行符
\r - 回车符
\t - 水平制表符
\v - 垂直制表符
%% - 单个%符号

常用的类型转换符:

%d - 将参数打印为十进制整数
%f - 将参数打印为浮点数
%s - 将参数打印为字符串
%x - 将参数打印为十六进制整数
%o - 将参数打印为八进制整数
[root@andy1 ~]# printf "姓名:%s\n年龄:%d\n工资:%.3f\n十六进制:%x\n" "小明" 28 1234.5678 110
姓名:小明
年龄:28
工资:1234.568
十六进制:6e
[root@andy1 ~]# 
  1. 多余的参数会继续输出
[root@andy1 ~]# printf "%s\t%d\t%s\n" "小明" 28 "男" "小王" 28 "男" "小张"
小明	28	男
小王	28	男
小张	0	
[root@andy1 ~]# 
  1. 左右对齐和前景背景色变化
    %-10s , %-8d其中-表示靠左对齐,默认情况下是靠右对齐。10和8表示占用10或者8个字符宽度。

\e[1,30;47m … \e[0m表示使用粗体字、黑色字体、白色背景,后面的\e[0,m表示重置

在这里插入图片描述

五. 变量

5.1 自定义变量

5.1.1 定义自定义变量

变量名=变量值

5.1.2 引用变量

$变量名
${变量名}

5.1.3 查看所有变量,包括自定义和环境变量

set

5.1.4 取消变量

unset 变量名

5.1.5 自定义变量的作用范围

仅在当前shell有效

5.2 环境变量

5.2.1 定义环境变量

方法一:用export定义
export 变量名=变量值
方法二:用export将自定义变量转换为环境变量

[root@andy1 ~]# ip1=192.168.1.1
[root@andy1 ~]# ip2=192.168.1.2
[root@andy1 ~]# export ip1 ip2
[root@andy1 ~]# 

5.2.2 引用变量

$变量名
${变量名}

5.2.3 查看环境变量

env

5.2.4 取消变量

unset 变量名

5.2.5 自定义变量的作用范围

在当前shell和子shell中有效

5.3 项目中通常把所有自定义变量放入一个脚本中如public.sh, 在需要使用这些变量的脚本中用source public.sh或. public.sh来在本shell先执行这个公共脚本引入自定义变量,再使用

在这里插入图片描述

5.4 位置变量

$1 $2 ${3}

5.5 预定义变量

在这里插入图片描述

5.5.1

$* "$*" $@ "$@" 这四个的区别

当参数为 "a 1" b时这四个参数的表现:
1. $* 和 $@ 是一样的,只有有空格就当做是一个独立的字符串。 "a" "1" "b"
2. "$*" 把所有参数当做一个整体字符串。 "a 1 b"
3. "$@"最合理,会智能区分字符串。 "a 1" "b"

5.6 变量的长度

查询变量的长度用#

[root@andy1 testshell]# ip1=192.168.1.11
[root@andy1 testshell]# ip2="1234"
[root@andy1 testshell]# ip3=123
[root@andy1 testshell]# ip4=11.11
[root@andy1 testshell]# echo ${#ip1}
12
[root@andy1 testshell]# echo ${#ip2}
4
[root@andy1 testshell]# echo ${#ip3}
3
[root@andy1 testshell]# echo ${#ip4}
5
[root@andy1 testshell]# 

5.7 变量的赋值方式

5.7.1 显式赋值

ip1=192.168.1.1
ip2="192.168.1.1"
today=`date +%F`
today=$(date +%F)

shell变量默认都是字符串

[root@andy1 testshell]# t1=1
[root@andy1 testshell]# t2=2
[root@andy1 testshell]# t3=t1+t2
[root@andy1 testshell]# echo $t3
t1+t2
[root@andy1 testshell]# 

5.7.2 read从键盘读入变量值

[root@andy1 testshell]# read t1
123
[root@andy1 testshell]# echo $t1
123
[root@andy1 testshell]# read -p “提示信息:” t1
提示信息:456
[root@andy1 testshell]# echo $t1
456
[root@andy1 testshell]# read -t 3 -p “提示信息:” t1
提示信息:[root@andy1 testshell]#
[root@andy1 testshell]# read -n 2 t1
12[root@andy1 testshell]echo $t1
12
[root@andy1 testshell]# read t1 t2 t3
11 22 33
[root@andy1 testshell]# echo $t3
33
[root@andy1 testshell]#

5.8 定义和引用变量时单引号和双引号的区别

单引号:强引用

双引号:弱引用

[root@andy1 ~]# school=xiaoxue
[root@andy1 ~]# echo "${school} is good"
xiaoxue is good
[root@andy1 ~]# echo '${school} is good'
${school} is good
[root@andy1 ~]# 

在这里插入图片描述

5.9 命令替换

用反引号``  或 $(命令)
里面的shell命令会被先执行
[root@andy1 ~]# touch `date +%F`_file1.txt
[root@andy1 ~]# touch $(date +%F)_file2.txt
[root@andy1 ~]# ll *.txt
-rw-r--r--. 1 root root 4 Nov  5 23:11 1.txt
-rw-r--r--. 1 root root 0 Nov 10 17:55 2020-11-10_file1.txt
-rw-r--r--. 1 root root 0 Nov 10 17:55 2020-11-10_file2.txt
[root@andy1 ~]# disk1=`df -h | grep '/$' | awk '{print $4}'`
[root@andy1 ~]# echo $disk1
32G
[root@andy1 ~]# disk1=$(df -h | grep '/$' | awk '{print $4}')
[root@andy1 ~]# echo $disk1
32G

5.10 变量的运算

5.10.1 整数运算

5.10.1.1 方法一 expr

[root@andy1 ~]# expr 1 + 3
4
[root@andy1 ~]# num1=1 ; num2=2 ; expr $num1 + $num2
3

# 赋值用命令替换
[root@andy1 ~]# num=$(expr 4 \* 3)
[root@andy1 ~]# echo $num
12

# 支持的运算符:
+      -         \*     /        %

5.10.1.2 方法二 $(())

在这里插入图片描述
在这里插入图片描述

# 支持的运算符:
+      -         *     /        %       **

5.10.1.3 方法三 $[]

# 使用方法类似$(())
[root@andy1 ~]# num1=1;num2=2
[root@andy1 ~]# echo $[num1+num2]
3
[root@andy1 ~]# echo $[num1 + num2]
3
[root@andy1 ~]# echo $[$num1 + $num2]
3
[root@andy1 ~]# num=$[(1+4)/2**3]
[root@andy1 ~]# echo $num
0
[root@andy1 ~]# 

5.10.1.4 方法四let

[root@andy1 ~]# num1=1;num2=2
[root@andy1 ~]# let num3=num1+num2;echo $num3
3
[root@andy1 ~]# let num3=$num1+$num2;echo $num3
3
[root@andy1 ~]# let num4=6-9 ;echo $num4
-3
[root@andy1 ~]# let num4++;echo $num4
-2
[root@andy1 ~]# 

5.10.2 小数运算

5.11 变量内容的删除和替换

5.11.1 删除

5.11.1.1 从前往后删除,最短匹配
[root@andy1 testshell]# url=www.sina.com.cn
[root@andy1 testshell]# echo ${#url}
15
[root@andy1 testshell]# echo ${url#.}
www.sina.com.cn
[root@andy1 testshell]# echo ${url#www.}
sina.com.cn
[root@andy1 testshell]# echo ${url#*.}
sina.com.cn
[root@andy1 testshell]# echo ${url#www.sina.}
com.cn
[root@andy1 testshell]# echo ${url#sina}
www.sina.com.cn
[root@andy1 testshell]# echo ${url#?[a-z][a-z]}
.sina.com.cn
5.11.1.2 从前往后删除,贪婪匹配
url=www.sina.com.cn
[root@andy1 testshell]# echo ${url##tt}
www.sina.com.cn
[root@andy1 testshell]# echo ${url##*.}
cn
5.11.1.3 从后往前删除,最短匹配
url=www.sina.com.cn
[root@andy1 testshell]# echo ${url%cn}
www.sina.com.
[root@andy1 testshell]# echo ${url%.*}
www.sina.com

5.11.1.4 从后往前删除,贪婪匹配
url=www.sina.com.cn
[root@andy1 testshell]# echo ${url%%.*}
www
5.11.1.5 切片

${变量名:从第几个字符开始取值:取几个值}

[root@andy1 testshell]# echo ${url:0:5}
www.s
[root@andy1 testshell]# echo ${url:5:5}
ina.c
[root@andy1 testshell]# echo ${url:5}
ina.com.cn
[root@andy1 testshell]# echo ${url::5}
www.s
[root@andy1 testshell]# echo ${url:5:5}
ina.c
[root@andy1 testshell]# echo ${url:5:1}
i

5.11.2 替换

  1. ${变量名/原值/新值}
  2. ${变量名//原值/新值}
  3. ${变量名-新的变量值}
  4. ${变量名:-新的变量值}
  5. ${变量名+新的变量值}
  6. ${变量名:+新的变量值}
  7. ${变量名=新的变量值}
  8. ${变量名:=新的变量值}
5.11.2.1 ${变量名/原值/新值} 或 ${变量名//原值/新值}
[root@andy1 ~]# url="www.sina.com.sina.cn"
[root@andy1 ~]# echo ${url/sina/sohu}
www.sohu.com.sina.cn
[root@andy1 ~]# echo ${url//sina/sohu}
www.sohu.com.sohu.cn
[root@andy1 ~]# 
5.11.2.2 ${变量名-新的变量值}
变量没定义:
	表达式的值:新值
	变量本身的值:不变
变量被赋空值:不变
	表达式的值:不变
	变量本身的值:
变量赋非空值:
	表达式的值:不变
	变量本身的值:不变
[root@andy1 ~]# unset t1 t2 t3
[root@andy1 ~]# t2=
[root@andy1 ~]# t3=test
[root@andy1 ~]# echo ${t1-wo}
wo
[root@andy1 ~]# echo ${t2-wo}

[root@andy1 ~]# echo ${t3-wo}
test
[root@andy1 ~]# echo $t1:$t2:$t3
::test

5.11.2.3 ${变量名:-新的变量值}
变量没定义:
	表达式的值:新值
	变量本身的值:不变
变量被赋空值:
	表达式的值:新值
	变量本身的值:不变
变量赋非空值:
	表达式的值:不变
	变量本身的值:不变
[root@andy1 ~]# unset t1 t2 t3
[root@andy1 ~]# t2=
[root@andy1 ~]# t3=test
[root@andy1 ~]# echo ${t1:-wo}
wo
[root@andy1 ~]# echo ${t2:-wo}
wo
[root@andy1 ~]# echo ${t3:-wo}
test
[root@andy1 ~]# echo $t1:$t2:$t3
::test
5.11.2.3 ${变量名+新的变量值}
变量没定义:
	表达式的值:不变
	变量本身的值:不变
变量被赋空值:
	表达式的值:新值
	变量本身的值:不变
变量赋非空值:
	表达式的值:新值
	变量本身的值:不变
[root@andy1 ~]# unset t1 t2 t3
[root@andy1 ~]# t2=
[root@andy1 ~]# t3=test
[root@andy1 ~]# echo ${t1+wo}

[root@andy1 ~]# echo ${t2+wo}
wo
[root@andy1 ~]# echo ${t3+wo}
wo
[root@andy1 ~]# echo $t1:$t2:$t3
::test
[root@andy1 ~]# 
5.11.4. ${变量名:+新的变量值}
变量没定义:
	表达式的值:不变
	变量本身的值:不变
变量被赋空值:
	表达式的值:不变
	变量本身的值:不变
变量赋非空值:
	表达式的值:新值
	变量本身的值:不变
[root@andy1 ~]# unset t1 t2 t3
[root@andy1 ~]# t2=
[root@andy1 ~]# t3=test
[root@andy1 ~]# echo ${t1:+wo}

[root@andy1 ~]# echo ${t2:+wo}

[root@andy1 ~]# echo ${t3:+wo}
wo
[root@andy1 ~]# echo $t1:$t2:$t3
::test
5.11.5. ${变量名=新的变量值}
变量没定义:
	表达式的值:新值
	变量本身的值:新值
变量被赋空值:
	表达式的值:不变
	变量本身的值:不变
变量赋非空值:
	表达式的值:不变
	变量本身的值:不变
[root@andy1 ~]# unset t1 t2 t3
[root@andy1 ~]# t2=
[root@andy1 ~]# t3=test
[root@andy1 ~]# echo ${t1=wo}
wo
[root@andy1 ~]# echo ${t2=wo}

[root@andy1 ~]# echo ${t3=wo}
test
[root@andy1 ~]# echo $t1:$t2:$t3
wo::test
5.11.6. ${变量名:=新的变量值}
变量没定义:
	表达式的值:新值
	变量本身的值:新值
变量被赋空值:
	表达式的值:新值
	变量本身的值:新值
变量赋非空值:
	表达式的值:不变
	变量本身的值:不变
[root@andy1 ~]# unset t1 t2 t3
[root@andy1 ~]# t2=
[root@andy1 ~]# t3=test
[root@andy1 ~]# echo ${t1:=wo}
wo
[root@andy1 ~]# echo ${t2:=wo}
wo
[root@andy1 ~]# echo ${t3:=wo}
test
[root@andy1 ~]# echo $t1:$t2:$t3
wo:wo:test
[root@andy1 ~]# 

六. 条件判断

6.1 if

if [ 1 -eq 0 ];then echo '1'
elif [ 1 -eq 2 ];then echo '2'
else echo '3'

fi

6.1.1 if的条件表达式有以下几种

  1. if后面跟[]表达式
[root@andy1 testshell]# if [ 1 -eq 1 ];then echo "yes";else echo "no";fi
yes
  1. if后面跟test表达式
[root@andy1 testshell]# if test 1 -eq 1; then echo "yes"; else echo "no"; fi
yes
  1. if后面跟:
    : 表示真,等价于true
[root@andy1 testshell]# if : ;then echo "yes"; fi
yes
  1. if后面跟true
[root@andy1 testshell]# if true ;then echo "yes"; fi
yes
  1. if后面跟一个命令,当命令正确执行时为真;命令执行报错时为假
[root@andy1 testshell]# if  ls &>/etc/null; then echo "yes"; else echo "no"; fi
yes
[root@andy1 testshell]# if  lsabc &>/etc/null; then echo "yes"; else echo "no"; fi
no

  1. 检查一个命令或程序是否被安装但又不用执行这个程序
[root@andy1 testshell]# if command -v /usr/bin/date &>/etc/null; then echo "yes"; else echo "no"; fi
yes

[root@andy1 testshell]# if command -v date ; then echo "yes"; else echo "no"; fi
/usr/bin/date
yes

[root@andy1 testshell]# if command -v python ; then echo "yes"; else echo "no"; fi
/usr/bin/python
yes

[root@andy1 testshell]# if command -v python3 ; then echo "yes"; else echo "no"; fi
/usr/bin/python3
yes

[root@andy1 testshell]# if command -v python4 ; then echo "yes"; else echo "no"; fi
no

七. 循环

7.1 for循环

for循环有三种写法:

shell写法:for i in 
C写法:for((i=1;i<5;i++))
从命令参数或函数参数取值的写法: for i

7.1.1 do和done之间可以用{}&括起来要执行的内容,是放到后台并发执行;在done后用wait来等待所有后台程序执行完毕再往下执行

if [ "$#" -eq 0 ]
then
        cat <<-EOF
Usage:ping.sh file
        EOF
        exit 222
fi

for ip in $(cat $1)
do
        {
        ping -c1 $ip &>/dev/null
        if [ $? -eq 0 ];then
                echo "$ip 在线"
        else
                echo "$ip 不在线"

        fi
        }&

done
wait
echo "finished"

7.1.2 for循环中的迭代对象默认以空格或tab分割,这样如果是读取文件中的内容,文件中一行有空格会被分别读取,可以用IFS修改分割符

# 把分隔符改为回车
IFS=$'\n'
或
IFS='
'

7.1.3 for i的用法

7.1.3.1 从命令参数取值

#!/bin/bash
for i
do
        echo "$i"
        echo "==="
done
[root@andy1 ~]# ./test.sh andy tom lucy
andy
===
tom
===
lucy
===

7.1.3.2 从函数参数取值

[root@andy1 ~]# vi test.sh

#!/bin/bash

test() {

        for i
        do
                echo "$i"
                echo "===="
        done

}

test andy tom wo
[root@andy1 ~]# ./test.sh
andy
====
tom
====
wo
====

7.2 while循环

7.2.1 while后可以加任何能返回真假的表达式

true,false,:
test 表达式
[ 表达式 ]
表达式

7.2.2 while与read配合从文件或其他进程的输出读取数据

  1. 从其他进程的输出读取数据
/dt/curr/engine/tools/dhcpserver_dump.sh show scope | grep -E "\S+\.\S+\." | awk -F '-' '{print $1}' | while read line
do
	TEXT=$(echo $line | tr -d "\n")
	/dt/curr/engine/tools/dhcpserver_dump.sh scope $TEXT initiate reconcile
done
  1. 从文件读取数据
while read line
do
        user[++i]=$line
done < /etc/passwd

7.2.3 while读取文件时是会读取空行的

[root@DTOS data]# cat while.sh 
#!/bin/bash

while read line
do
	{
	if [ -z "$line" ]
	then
		echo "有一个空行"
		continue	
	fi	
	if ping -c1 $line &>/dev/null
	then
		echo "$line 在线"
	else
		echo "$line 不在线"
	fi
	}&
done < $1

wait
echo "finished...."
[root@DTOS data]# bash while.sh ip.txt 
有一个空行
有一个空行
有一个空行
有一个空行
192.168.1.1 在线
192.168.1.2 在线
192.168.1.7 在线
192.168.1.9 在线
192.168.1.6 在线
192.168.1.5 在线
192.168.1.17 在线
192.168.1.15 在线
192.168.1.12 在线
192.168.1.3 不在线
192.168.1.4 不在线
192.168.1.8 不在线
192.168.1.11 不在线
192.168.1.10 不在线
192.168.1.13 不在线
192.168.1.14 不在线
192.168.1.16 不在线
192.168.1.18 不在线
192.168.1.19 不在线
192.168.1.20 不在线
finished....

7.3 until循环

7.2.1 until后可以加任何能返回真假的表达式

true,false,:
test 表达式
[ 表达式 ]
表达式

[root@DTOS data]# i=1
[root@DTOS data]# until [ $i -eq 10 ]
> do {
> echo $i
> }&
> let i++
> done
[1] 17412
1
[2] 17413
2
[3] 17414
3
[4] 17415
4
[5] 17416
5
[6] 17417
6
[7] 17418
7
[8] 17419
8
[9] 17420
9
[1]   Done                    { echo $i; }
[2]   Done                    { echo $i; }
[3]   Done                    { echo $i; }
[4]   Done                    { echo $i; }
[5]   Done                    { echo $i; }
[6]   Done                    { echo $i; }
[7]   Done                    { echo $i; }
[8]-  Done                    { echo $i; }
[root@DTOS data]# 

7.4 select循环

[root@rh2 ~]# cat select.sh 
#!/bin/bash
PS3="请输入选项:"
select name in "andy" "tony" "linda" "emily" "exit"
 	do
 		case "$name" in 
 			andy)
 				echo andy
 				;;
 			tony)
 				echo tony
 				;;
 			linda)
 				echo linda
 				;;
 			emily)
 				echo emily
 				;;
 			exit)
 				exit
 				;;
 		esac
 	
 	done

八. expect

send命令接收一个字符串参数,并将该参数发送到进程。
expect命令和send命令相反,expect通常用来等待一个进程的反馈,我们根据进程的反馈,再发送对应的交互命令。
spawn命令用来启动新的进程,spawn后的send和expect命令都是和使用spawn打开的进程进行交互。
interact命令用的其实不是很多,一般情况下使用spawn、send和expect命令就可以很好的完成我们的任务;但在一些特殊场合下还是需要使用interact命令的,interact命令主要用于退出自动化,进入人工交互。比如我们使用spawn、send和expect命令完成了ftp登陆主机,执行下载文件任务,但是我们希望在文件下载结束以后,仍然可以停留在ftp命令行状态,以便手动的执行后续命令,此时使用interact命令就可以很好的完成这个任务。

8.1 语法

命令    作用
set                 定义变量
puts                打印字符串或变量的值 puts "test"                或        puts $test
set timeout 30:设置超时时间,单位为秒,默认情况下是10秒;
set host "101.200.241.109":设置变量;
spawn ssh $username@$host:spawn是进入expect环境后才可以执行的expect内部命令,如果没有装expect或者直接在默认的SHELL下执行是找不到spawn命令的。它主要的功能是给ssh运行进程加个壳,用来传递交互指令;
send    用于向进程发送字符串
expect    从进程接收字符串
spawn    启动新的进程
interact    执行完成后保持交互状态,把控制权交给控制台,这个时候就可以手工操作了。如果没有这一句登录完成后会退出,而不是留在远程终端上。
eof                 expect执行结束 退出
expect eof :等待执行结束,若没有这一句,可能导致命令还没执行,脚本就结束了.expect eof 与 interact 二选一即可
expect "*password*":这里的expect也是expect的一个内部命令,这个命令的意思是判断上次输出结果里是否包含“password”的字符串,如果有则立即返回;否则就等待一段时间后返回,这里等待时长就是前面设置的30秒;
send "$password\r":当匹配到对应的输出结果时,就发送密码到打开的ssh进程,执行交互动作;
exp_continue        在expect中多次匹配就需要用到
send_user           用来打印输出 相当于shell中的echo
exit                退出expect脚本

8.2 expect可以有多个分支,就像switch语句一样。

# 条件:匹配不同字符串执行不同send
expect {
        "字符串1" { send "字符串" }
        "字符串2" { send "字符串" }
        "字符串3" { send "字符串" }
}
# 如果某个send 字符串后加上 ; exp_continue表示如果在这个switch中命中这个字符串后,还会待在这个switch中去继续匹配
expect {
        "字符串1" { send "字符串"; exp_continue }
        "字符串2" { send "字符串"; exp_continue }
        "字符串3" { send "字符串"; exp_continue }
}
# 例子
expect {
        "yes/no" { send "yes\r" }
        "#" { send "ll\r" }
        "password" { send "admin@123\r"; exp_continue }
}

8.3 执行脚本时位置参数的使用

用 [lindex $argv 0] 来引用第一个位置参数
用 [lindex $argv 1] 来引用第二个位置参数
。。。。。。

在这里插入图片描述root@DTOS data]# ./e.sh 192.168.1.228 admin@123

8.4 不需要人工交互时脚本结尾要加 expect eof

在这里插入图片描述

# 如果不用expect eof结尾,在执行完最后一条命令命令后要等待一个timeout时间后就退出程序了,而不管这时这个命令有没有执行完

8.5 在shell脚本中使用expect

在这里插入图片描述

8.6 send中的命令如果有; 如果转义不作为两个语句的分割

用’;’
在这里插入图片描述

8.7 if条件判断

if { condition } {
     # do your things
} elseif {
     # do your things
} else {
     # do your things
}
# expect中没有小括号(),所有的if/else, while, for的条件全部使用大括号{},
# { 和}的左边和右边都要有空格,否则会报错。另外else 不能单独占一行,否则会报错

8.8 switch 语句

switch $location {
    "apple" { puts "apple" }
    "banana" { puts "banana" }
    default {
        puts "other"
     }
}

记得左大括号{ 的左边要有空格,否则会报错

九. 多进程执行任务

9.1 {}&方式

# 这种方式是一次把所有任务都后台运行起来,这样可能会有问题
#!/bin/bash

for i in {1..1000}
do
        {
        useradd test$i
        "test" |passwd --stdin test$i

        }&

done
wait
echo "finished!!!!!!!!!!!!!!!!!!!!!!!!!!"
这样把所有任务一起执行可能会有错误
passwd: Unknown user name 'test967'.
passwd: Unknown user name 'test873'.
passwd: Unknown user name 'test958'.
useradd: cannot lock /etc/passwd; try again later.
passwd: Unknown user name 'test879'.
useradd: cannot lock /etc/passwd; try again later.
useradd: cannot lock /etc/passwd; try again later.

9.2 用命名管道文件的文件描述符中放入数据的数量来限制{}&方式一次能同时执行任务的数量

# 原理:用read -u 来读取命名管道文件中的数据,如果管道文件中有数据就继续往下执行{}&中的任务,如果管道文件中没数据了就阻塞一会等待管道文件中再次有数据,而每个{}&任务执行完毕时会向管道文件中写入一个数据来允许再运行一个任务
#!/bin/bash

fifofile=/tmp/$$.fifo
# 创建一个命名管道文件
mkfifo $fifofile
# 建立一个文件描述符10指向这个命名管道文件
exec 10<> $fifofile
# 删除这个命名管道文件
rm -rf $fifofile

# 指定同一时间运行的进程个数
process=5

# 首先向命名管道文件的文件描述符中放入process个任意字符
for i in `seq $process`
        do
                # &10指文件描述符10
                echo >&10
        done

for i in {1..1000}
do
        # read -u 是从一个文件描述符中读取数据,后面跟文件描述符。 如果该文件描述符中无数据会阻塞在这>里一直到再次有数据
        read -u 10
        {
        useradd tester$i
        "test" |passwd --stdin tester$i

        # 每次执行完一个任务要向文件描述符中还一个字符
        echo >&10

        }&

done
wait
# 关闭文件描述符
exec 10<&-
echo "finished!!!!!!!!!!!!!!!!!!!!!!!!!!"

十. 数组

字符串变量、普通数组变量、关联数组变量的索引
在这里插入图片描述

10.1 普通数组

相当于python的列表;
用数字做索引;

10.1.1 定义普通数组

10.1.1.1 方法一:一次赋一个值
# 数组变量名[下标]=变量值
[root@andy1 ~]# arry1[0]=a
[root@andy1 ~]# arry1[2]=c
[root@andy1 ~]# arry[100]=z
10.1.1.2 方法二:一次赋多值
[root@andy1 ~]# arry2=(andy tom tony)
# 数组的各个值之间是以空格分隔的,而passwd文件中一行中有多个空格,所以变量个数要多余行数
[root@andy1 ~]# arry3=(`cat /etc/passwd`)
[root@andy1 ~]# arry4=(`ls`)
[root@andy1 ~]# arry5=(andy tom "test tt")
[root@andy1 ~]# red="r"; blue="b"; green="g"
[root@andy1 ~]# arry6=($red $blue $green)
# 可以手动指定索引
[root@andy1 ~]# arry7=(1 2 3 "test tt" [20]=andy)

10.1.2 查看普通数组

10.1.2.1 查看系统中所有的普通数组
[root@andy1 ~]# 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]="2" [2]="46" [3]="2" [4]="release" [5]="x86_64-redhat-linux-gnu")'
declare -a DIRSTACK='()'
declare -a FUNCNAME='()'
declare -a GROUPS='()'
declare -a PIPESTATUS='([0]="0")'
declare -a arry='([100]="z")'
declare -a arry1='([0]="a" [2]="c")'
declare -a arry2='([0]="andy" [1]="tom" [2]="tony")'

10.1.3 访问普通数组中的元素

# 访问第二个元素
[root@andy1 ~]# echo ${arry7[1]}
2
# 访问所有元素
[root@andy1 ~]# echo ${arry7[@]}
1 2 3 test tt andy
# 访问所有元素
[root@andy1 ~]# echo ${arry7[*]}
1 2 3 test tt andy
# 查看元素个数
[root@andy1 ~]# echo ${#arry7[*]}
5
[root@andy1 ~]# echo ${#arry7[@]}
5

10.1.4 获取普通数组中的索引

${!数组变量名[@]}

[root@andy1 ~]# echo ${!arry7[@]}
0 1 2 3 20

10.1.5 普通数组的切片

[root@andy1 ~]# echo ${arry7[@]}
1 2 3 test tt andy
# 从下标3开始取
[root@andy1 ~]# echo ${arry7[@]:3}
test tt andy
# 从下标1开始取,取2个值
[root@andy1 ~]# echo ${arry7[@]:1:2}
2 3

10.1.6 遍历普通数组

10.1.6.1 通过元素变量
[root@localhost ~]# lst1=(a b c)
[root@localhost ~]# for i in ${lst1[*]}
> do
> echo $i
> done
a
b
c
10.1.6.2 通过索引遍历
#!/bin/bash

while read line
do
        user[++i]=$line
done < /etc/passwd

for i in ${!user[@]}
do
        echo $i" : "${user[i]}
done

10.1.7 向普通数组中添加元素

[root@slave01 ~]# list=()
[root@slave01 ~]# list[${#list[@]}]=andy
[root@slave01 ~]# echo ${#list[@]}
1
[root@slave01 ~]# list[${#list[@]}]=tony
[root@slave01 ~]# echo ${#list[@]}
2

10.2 关联数组

相当于python的字典
用字符串做索引;

10.2.1 定义关联数组-declare -A

关联数组需要事先用declare -A来定义,否则就是普通数组

10.2.2 关联数组定义方法一:一次赋一个值

# 变量名[索引]=变量值
[root@andy1 ~]# declare -A ass_arry1
[root@andy1 ~]# ass_arry1[name]=andy
[root@andy1 ~]# ass_arry1[age]=18
[root@andy1 ~]# ass_arry1[sex]=男

10.2.3 关联数组定义方法二:一次赋多个值

[root@localhost ~]# declare -A lst2=([name]=andy [age]=18 [sex]=男)

10.3 将文件中的内容按行放入普通数组中

10.3.1 用while循环放

#!/bin/bash

while read line
do
        user[++i]=$line
done < /etc/passwd

for i in ${!user[@]}
do
        echo $i" : "${user[i]}
done

10.3.2 用for循环放

#!/bin/bash
OLD_IFS=$IFS
IFS=$'\n'
for line in `cat /etc/passwd`
do
        user[++i]=$line
done

for i in ${!user[@]}
do
        echo $i" : "${user[i]}
done
IFS=$OLD_IFS

10.3.3 直接cat获得

[root@localhost ~]# OLD_IFS=$IFS
[root@localhost ~]# IFS=$'\n'
[root@localhost ~]# lst1=(`cat /etc/passwd`)
[root@localhost ~]# for line in ${lst1[*]}
> do
> echo $line
> done
[root@localhost ~]# IFS=$OLD_IFS

10.4 从某个文件或输出中计算某列数据中每个值出现几次

用列的值作为关联数组的索引

#!/bin/bash

while true
do
        clear
        unset nets
        declare -A nets
        for connect in `ss -an |awk '{print $2}'`
        do
        		# 把ss -an 输出中的第二列连接状态类型作为关联数组nets的索引,然后每出现一次其值++一次
                let nets[$connect]++
        done

        for i in ${!nets[@]}
        do
                echo "$i:""${nets[$i]}"
        done
        sleep 2
done
ESTAB:157
TIME-WAIT:25
UNCONN:74
State:1
LISTEN:28

10.5 从数组中删除元素、删除整个数组

10.5.1 按索引删除元素

unset 数组名[索引]

10.5.2 按元素删除元素

array=(${array[@]/要删除的字符串})

[root@localhost ~]# lst1=(andy tony linda tony)
[root@localhost ~]# name=tony
[root@localhost ~]# lst2=(${lst1[@]/$name})
[root@localhost ~]# echo ${lst2[@]}
andy linda
[root@localhost ~]# lst2=(${lst1[@]/ny})
[root@localhost ~]# echo ${lst2[@]}
andy to linda to
[root@localhost ~]# lst2=(${lst1[@]/*ny})
[root@localhost ~]# echo ${lst2[@]}
andy linda

10.5.3 删除整个数组

unset 数组名

10.6 修改数组中元素

数组名[索引]=新值

10 7 替换数组中字符串

[root@localhost ~]# echo ${lst1[*]/to*/123}
andy 123 kangkai
[root@localhost ~]# echo ${lst1[*]/kang/123}
andy tony 123kai

10.8 查询数组中是否包含某个字符串

十一. 函数

11.1 函数的定义

function func1(){
echo ‘i am func1’
}

func2(){
echo ‘i am func2’
}

11.2 函数的调用

func1
func1 参数1 参数2 参数3

11.3 向函数中传参数

#!/bin/bash
name=“andy”
function func1(){
echo “i am $name”
}

func1

11.4 函数调用时的位置参数

调用函数时 加位置参数;
函数里面的$1是第一个位置参数

#!/bin/bash
function func1(){
echo "i am $1"
echo "you are $2"
}

func1 andy tom

11.5 调用函数后的$?值

调用函数后$?的值是函数中最后一条语句执行的结果。如果执行成功是0;执行失败是非0

#!/bin/bash
test() {
dat &>/dev/null
}

test
echo $?

[root@andy1 ~]# vi test.sh
[root@andy1 ~]# ./test.sh
127
#!/bin/bash
test() {
date &>/dev/null
}

test
echo $?
[root@andy1 ~]# ./test.sh
0

11.6 函数的return返回值

return只能return小于255的整数数字,否则返回的值很奇怪;
如果想返回非0-255的内容,请看11.7

#!/bin/bash
test() {
date
return 130
}

test
echo $?

[root@andy1 ~]# ./test.sh
Wed Dec 23 14:53:02 CST 2020
130

11.7 通过把函数的执行结果赋给一个变量来获取函数的输出

#!/bin/bash
test() {
date
}
# 将函数执行的输出赋值给a来带出函数
a=`test`
echo $a

[root@andy1 ~]# ./test.sh
Wed Dec 23 14:58:48 CST 2020

#!/bin/bash

test(){
date
echo 123
echo "i am $2"
}

a=$(test "andy" "tom")
echo ===================
echo $a


[root@andy1 ~]# ./test.sh 
===================
Wed Jan 6 09:42:07 CST 2021 123 i am tom
[root@andy1 ~]# 

11.8 函数外和函数内的变量默认都是全局变量,能互相使用

#!/bin/bash
a=andy
test() {
        echo "我在函数里 "$a
        a=tom

}
echo "我在函数外"$a
test
echo "我在函数外"$a
[root@andy1 ~]# ./test.sh
我在函数外andy
我在函数里 andy
我在函数外tom

11.9 函数内的变量可以加local来指定为局部变量

#!/bin/bash
a=andy
test() {
local a
a=tom
echo "我在函数里 "$a

}
test
echo “我在函数外”$a

11.10 使用数组来给函数传参数

  1. 调用函数时用数组的值做参数: 函数名 ${数组名[@]}
  2. 在函数中$@为数组参数的值
  3. 在函数中$#为数组参数的个数
#!/bin/bash

test() {
        echo "函数收到的数组是:"$@
        echo "函数收到的数组的长度是:"$#
}

arry=(andy tom tony)
test ${arry[@]}

11.11 用`` 或 $()执行的命令是在子shell中执行的,所以里面的变量不可被外面用

例如:下面函数test内定义了一个全局变量num,但在脚本中执行函数是在子shell中执行的,所以本shell没有变量num

#!/bin/bash
test() {
        echo 9
        num=3
}

a=`test`
echo "a:"$a
echo "num:"$num
[root@andy1 ~]# ./test.sh
a:9
num:

十二. 影响shell执行的内部命令

12.1 :

冒号是true
冒号也相当于python的pass占位用

12.2 break continue

这两个后面都可以加数字,不加或加1表示退出1层,加2表示退出2层

12.3 shift

使脚本或函数的位置变量向左移几位
shift 等于 shift 1
可以用shift 2 等一次移动多个

#!/bin/bash

while [ $# -ne 0 ]
do
        echo $1
        shift 2
done
[root@andy1 ~]# bash test.sh 1 2 3 4
1
3

十三. 正则表达式

13.1 基本元字符

在这里插入图片描述在这里插入图片描述

13.2 扩展元字符

在这里插入图片描述

15. tr的用法

主要用于压缩重复字符,删除文件中的控制字符以及进行字符转换操作

15.1 替换字符 -t

# 把a换成1;b换成2
[root@DTOS data]# echo "aabbccdd" |tr -t ac 12
11bb22dd
# 把b和d都换行换行
[root@DTOS data]# echo "aabbccdd" |tr -t bd "\n""\n"
aa

cc


15.2 替换并滤重字符 -s

# 单纯去重连续a
[root@DTOS data]# echo "aabbccddaa" |tr -s "a" 
abbccdda
# 把a换成1,c换成2并去掉连续重复的
[root@DTOS data]# echo "aabbccddaa" |tr -s ac 12
1bb2dd1
# 把abc都变成w,w有连续重复的也去掉
[root@DTOS data]# echo "aabbccddaa" |tr -s abc w
wddw

15.3 删除字符 -d

# 删除a到c的字符
[root@DTOS data]# echo "aabbccddaa" |tr -d a-c
dd
# 删除所有换行
tr -d "\n"

15.4 反向替换 -c

# 把不是a的字符都换成#
[root@DTOS data]# echo "aabbccddaa" |tr -c a "#"
aa######aa#[root@DTOS data]# 

十六. 编码转换iconv

16.1 列出当前支持的字符编码

-f和-t所能指定的合法字符在-l选项的命令里面都列出来了

[root@DTOS data]# iconv -l
The following list contain all the coded character sets known.  This does
not necessarily mean that all combinations of these names can be used for
the FROM and TO command line parameters.  One coded character set can be
listed with several different names (aliases).

  437, 500, 500V1, 850, 851, 852, 855, 856, 857, 860, 861, 862, 863, 864, 865,
  866, 866NAV, 869, 874, 904, 1026, 1046, 1047, 8859_1, 8859_2, 8859_3, 8859_4,
  8859_5, 8859_6, 8859_7, 8859_8, 8859_9, 10646-1:1993, 10646-1:1993/UCS4,
  ANSI_X3.4-1968, ANSI_X3.4-1986, ANSI_X3.4, ANSI_X3.110-1983, ANSI_X3.110,

16.2 参数

-f encoding :把字符从encoding编码开始转换。 

-t encoding :把字符转换到encoding编码。 

-l :列出已知的编码字符集合 

-o file :指定输出文件 

-c :忽略输出的非法字符 

-s :禁止警告信息,但不是错误信息 

--verbose :显示进度信息 

-f和-t所能指定的合法字符在-l选项的命令里面都列出来了。

二. 杂乱知识点

2.1 在shell脚本中执行其他程序的代码

2.1.1 python python文件名

#!/usr/bin/bash
echo "i am shell"

python test.py

2.1.2 python 加<<重定向

#!/usr/bin/bash
echo "i am shell"

python << EOF
print("i am python")
print('test')
EOF

2.2 查看linux中支持的shell

[root@master andy]# cat /etc/shells 
/bin/sh
/bin/bash
/sbin/nologin
/usr/bin/sh
/usr/bin/bash
/usr/sbin/nologin

2.3 执行脚本时显示执行详情

用参数-vx

在这里插入图片描述

2.4 只检查脚本不执行

用参数-n

[root@DTOS data]# bash -n t.sh 
[root@DTOS data]# 

2.5 i++ 和 ++i

i++ 先赋值再运算
++i 先运算再赋值

2.5.1 对变量的值的影响(二者无区别)

2.5.2 对表达式的值的影响(二者有区别)

[root@DTOS data]# for i in {1..5}; do echo “这次是:”$i; let y=i++; echo "然后是:"$y; done
“这次是:”1
然后是:1
“这次是:”2
然后是:2
“这次是:”3
然后是:3
“这次是:”4
然后是:4
“这次是:”5
然后是:5
[root@DTOS data]# 
[root@DTOS data]# for i in {1..5}; do echo “这次是:”$i; let y=++i; echo "然后是:"$y; done
“这次是:”1
然后是:2
“这次是:”2
然后是:3
“这次是:”3
然后是:4
“这次是:”4
然后是:5
“这次是:”5
然后是:6

2.6 只读变量

不能改也不能删除

[root@andy1 ~]# readonly t=444
[root@andy1 ~]# 

2.7 数组

bash支持一维数组(不支持多维数组),并且没有限定数组的大小。用括号来表示数组,数组元素用空格符号分割开。定义数组的一般形式为:

数组元素的下标由0开始编号。获取数组中的元素要利用下标,下标可以是整数或算术表达式,其值应大于或等于0。

2.7.1 数组变量的声明

  1. 数组名=(值1 值2 … 值n)
[root@andy1 ~]# lst1=(1 test $HOSTNAME)
[root@andy1 ~]# echo $lst1[2]
1[2]
[root@andy1 ~]# echo $lst1[0]
1[0]
[root@andy1 ~]# echo ${lst1[0]}
1
[root@andy1 ~]# echo ${lst1[1]}
test
[root@andy1 ~]# echo ${lst1[2]}
andy1
[root@andy1 ~]# echo ${lst1[3]}

[root@andy1 ~]# echo ${lst1[-3]}
1
[root@andy1 ~]# echo ${lst1[-1]}
andy1
[root@andy1 ~]# echo ${lst1[-111]}
-bash: lst1: bad array subscript
  1. 数组名[下标]=值
[root@andy1 ~]# unset lst1
[root@andy1 ~]# lst1[3]=3
[root@andy1 ~]# lst1[6]=6
[root@andy1 ~]# echo ${lst1[3]}
3
[root@andy1 ~]# echo ${lst1[0]}

[root@andy1 ~]# echo ${lst1[100]}

[root@andy1 ~]# echo ${lst1[@]}
3 6

2.7.2 数组的引用

  1. 用下标引用
[root@andy1 ~]# echo ${lst1[3]}
  1. 用@引用所有
[root@andy1 ~]# echo ${lst1[@]}

2.8 trap捕捉信号

trap语法如下 :

trap command signals

trap命令的参数分为两部分,前一部分是接收到指定信号时将要采取的行动,通常是一个函数,要用双引号引起函数名,后一部分是要处理的信号名.请记住,脚本程序通常是以从上到下的顺序解释执行的,所以必须在你想保护的那部分代码以前指定trap命令。

如果要重置某个信号的处理条件到其默认值,只需简单的将command设置为-。如果要忽略某个信号,就把command设置为空字符串‘’。一个不带参数的trap命令将列出当前设置的信号及其行动的清单。
[bastion@andy1 ~]$ trap
trap -- '' SIGTSTP
trap -- '' SIGTTIN
trap -- '' SIGTTOU
[bastion@andy1 ~]$ trap "" hup
[bastion@andy1 ~]$ trap
trap -- '' SIGHUP
trap -- '' SIGTSTP
trap -- '' SIGTTIN
trap -- '' SIGTTOU
[bastion@andy1 ~]$ trap - hup
[bastion@andy1 ~]$ trap
trap -- '' SIGTSTP
trap -- '' SIGTTIN
trap -- '' SIGTTOU
[bastion@andy1 ~]$ 
trap "" HUP INT OUIT TSTP

2.9 测试脚本运行时间

用time bash 脚本名

2.10 每隔几秒循环执行一个shell脚本文件

用watch -n 秒数 脚本文件路径

[root@DTOS data]# watch -n 2 ./count_net.sh
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值