脚本进阶一

一、for循环的第二种写法:

众所周知,for有两种写法

第一种:for i in k8s-node{1..3};do setenforce 0;done

第二种写法:C语言风格

直接写怎么用:

#for后必须写两个括号,又称双小括号写法

[[email protected] ~]# cat for_2.sh

#!/bin/bash

for ((i=1,sum=0;i<=100;i++));do

let sum+=i

done

echo "sum=${sum}"

[[email protected] ~]# bash for_2.sh

sum=5050

二、while循环

我喜欢这样写,一直循环然后用break退出

[[email protected] ~]# cat while_sum.sh

#!/bin/bash

i=1

sum=0

while true;do

let sum+=i

let i++

if [ $i -gt 100 ];then

break

fi

done

echo "sum=${sum}"

[[email protected] ~]# bash while_sum.sh

sum=5050

while的高级用法:读取标准输入的内容实现循环

[[email protected] ~]# cat while_2.sh

#!/bin/bash

while read line

do

echo $line

done < /etc/fstab

[[email protected] ~]# bash while_2.sh

#

# /etc/fstab

# Created by anaconda on Thu Aug 8 19:04:39 2019

#

# Accessible filesystems,by reference,are maintained under ‘/dev/disk‘

# See man pages fstab(5),findfs(8),mount(8) and/or blkid(8) for more info

#

/dev/mapper/centos-root / xfs defaults 0 0

UUID=3778e6e0-8f51-4843-8b8f-239c8b5e826b /boot xfs defaults 0 0

/dev/mapper/centos-home /home xfs defaults 0 0

/dev/mapper/centos-swap swap swap defaults 0 0

并且看网友的资料说,上面写法中wile使用重定向机制,fstab文件内容被重定向给了整个while语句,这个特性要注意下

while的注意事项1:管道传递内容:echo "abc xyz" | while read line ;do {};done 众所周知管道会开启子shell,子shell内的数组,变量,函数在函数外部均不生效

#!/bin/bash

echo "abc xyz" | while read line

do

new_var=$line

done

echo new_var is null: $new_var?

三、until循环

until CONDITION; do 循环体

done

进入条件: CONDITION 为false

退出条件: CONDITION 为true

四、continue特殊用法

continue [N]:提前结束第N层的本轮循环,最内层为第一层

默认N为1,只退一层循环。比如复杂的代码套了好几层的话,continue 2可以直接提前结束两层的循环,直接进入下一轮判断,continue候面的代码不执行了

五、break用法

break [N]:提前结束第N层循环,最内层为第1层

注意:这个直接结束第N层所有循环了,而continue只是结束第N层的本轮循环

六、shift命令

shift [n]

很重要,脚本中经常用到。将参数列表左移n次

[[email protected] ~]# cat shift.sh

#!/bin/bash

#判断脚本参数是否为0,不为0则执行循环

while [ $# -ne 0 ];do

echo $1 #打印第一个参数

shift #所有参数左移,第一个参数被挤走,第二个参数变成第一个参数

done

[[email protected] ~]# ./shift.sh a b c d f

a

b

c

d

f

七、select循环与菜单

select经常与case一起用;还有就是PS3作为提示符;还有就是要配合break或exit退出循环

[[email protected] ~]# cat select.sh

#!/bin/bash

PS3="你想干啥:"

select choice in eating wc sleep quit

do

case $choice in

eating)

echo "you can eat some food now."

;;

wc)

echo "you can go go to wc now."

;;

sleep)

echo "you can go to sleep now."

;;

quit)

exit 0

esac

done

[[email protected] ~]# bash select.sh

1) eating

2) wc

3) sleep

4) quit

你想干啥:1

you can eat some food now.

你想干啥:2

you can go go to wc now.

你想干啥:3

you can go to sleep now.

你想干啥:4

八、函数

载入函数:

. filename

source filename

可以使用unset删除

比如:一个简单的函数,执行没有问题

[[email protected] ~]# cat function.sh

#!/bin/bash

hi(){

echo hi

}

hi

[[email protected] ~]# bash function.sh

hi

中间加一行unset,就报错了,因为函数被删除了

[[email protected] ~]# cat function.sh

#!/bin/bash

hi(){

echo hi

}

unset hi

hi

[[email protected] ~]# bash function.sh

function.sh: line 6: hi: command not found

还可以通过定义空函数实现,这是我在系统中的脚本中发现的

# ubuntu的/lib/lsb/init-functions

# Pre&Post empty function declaration,to be overriden from /lib/lsb/init-functions.d/*

log_daemon_msg_pre () { :; }

log_daemon_msg_post () { :; }

log_begin_msg_pre () { :; }

log_begin_msg_post () { :; }

log_end_msg_pre () { :; }

log_end_msg_post () { :; }

log_action_msg_pre () { :; }

log_action_msg_post () { :; }

log_action_begin_msg_pre () { :; }

log_action_begin_msg_post () { :; }

log_action_end_msg_pre () { :; }

log_action_end_msg_post () { :; }

十、函数变量的生存时间

环境变量:当前shell和子shell有效

本地变量:只在当前shell进程中有效,包括脚本函数

局部变量:函数的生命周期,函数结束时变量销毁

局部变量的定义:local AGE=20

十一、函数的递归

联想到fork炸弹

:(){:|:&};:

脚本实现

cat bomb.sh

#!/bin/bash

./$0|./$0&

十二、信号的捕捉trap

看另一篇文章

Logo

K8S/Kubernetes社区为您提供最前沿的新闻资讯和知识内容

更多推荐