一、流程控制
1、过程式编程
顺序结构
循环结构
选择执行
2、if语句
单分支
if 条件 ;then # 探条件为真则执行
代码块
fi
多分支
if 条件 ; then
代码块
elif 条件 ;then # 多个elif 最后一个可不加;then
代码块
else
代码块
fi
3、case语句
case $i in
part1)
分支1
;;
...
esac
说明:case是通配符功能;*表示任意长度任意字符
? 任意单个字符
[] 指定范围内的任意单个字符
a|b a或b
4、for
for 变量名in 列表;do
循环体
done
执行机制:
依次将列表中的元素赋值给“变量名”; 每次赋值后即执行一次循环体; 直到列表中的元素耗尽,循环结束
列表生成方式:
(1) 直接给出列表
(2) 整数列表:
(a)
(b) $(seq[start [step]] end)
(3) 返回列表的命令
$(COMMAND)
(4) 使用glob,如:
*.sh
(5) 变量引用;
$@, $*
特殊用法
双小括号方法,即((...))格式,也可以用于算术运算
双小括号方法也可以使bash Shell实现C语言风格的变量操作
I=10
((I++))
for循环的特殊格式:
for ((控制变量初始化;条件判断表达式;控制变量的修正表达式))do
循环体
done
控制变量初始化:仅在运行到循环代码段时执行一次
控制变量的修正表达式:每轮循环结束会先进行控制变量修正运算,而后再做条件判断
5、while
while true ;do
循环体
done # 直到错误就退出
• while读取文件并处理(遍历文件的每一行)
while read line ;do
循环体
done
依次读取/path/to/file文件中的每一行,且将行复制给变量line
• continue:跳到某次循环;continue 2 表示跳到第二层循环(自己所在的层为第一层)
• break : 跳出某次循;break 2 表示跳出第二层循环(自己所在的为第一层)
• continue 2 break 1
实例:
vim addGecos.sh
#!/bin/bash
while read line ;do
Gecos=`echo $line | cut -d: -f 5`
name=`echo $line | cut -d : -f 1`
if [[ -z "$Gecos" ]];then
chfn -f $name -p 62985600 &>/dev/null
echo "$name info revise successfully"
else
continue
fi
done
实现监控磁盘分区
vim checkDisk.sh
df | grep "/dev/sd" | while read lines ;do
disk_used=`echo $lines | sed -r 's/.* ([0-9]+)%.*/\1/'`
disk_name=`echo $lines | cut -d " " -f 1`
if [ $lines -gt 80 ] ;then
echo "$disk_name will be full !!"
fi
done
6、until
until false ;do
循环体
done # 直到正确就退出
7、select语句
语法格式:
select variable in list
do
循环体
done
说明:select主要用于创建菜单,按照数字顺序排列的菜单向将显示在标准错误上,并显示PS3(select语句专用提示符号)提示符;等待用户输入。
用户输入菜单列表多种的某个数字,执行相应的命令
用户输入被保存在内置变量 REPLY 中
实例:打印点菜菜单,当用户输入选项时,输出相对应的价格
vim select_mem.sh
PS3="pls inpit a num: "
select Memu in remen rice lamb beef broccoli ;do
case $REPLY in
1)
echo 'The price is $10'
;;
2)
echo 'The price is $15'
;;
4)
echo 'The price is $20'
;;
5)
echo 'The price is $25'
;;
*)
break
;;
esac
done
select 是个无限循环,因此要记住用break 命令退出循环,或用exit 命令终止脚本。也可以按ctrl+c 退出循环
select 经常和case 联合使用;与for 循环类似,可以省略in list,此时使用位置参量
8、信号捕捉 trap
trap '触发指令' 信号 :自定义进程收到系统发出的指定信号后,将执行触发指令,而不会执行原操作
trap '' 信号忽略信号的操作
trap '-' 信号恢复原信号的操作
trap -p 列出自定义信号操作
实例:
#!/bin/bash
trap 'echo “signal:SIGINT"' int # 自定义了信号;例如;press ctrl+c 【写自己想执行的操作】表示当按下ctrl+c时不会中断只会显示press ctrl+c
trap -p # 显示信号列表
for((i=0;i
sleep 1
echo $i
done
trap '' int # 当按下ctrl+c时不会出现提示信息 ;int表示ctrl+c信号
trap -p
for((i=11;i
sleep 1
echo $i
done
trap '-' int # 恢复信号;按下ctrl+c时会中断程序运行
trap -p
for((i=21;i
sleep 1
echo $i
done
9、循环控制shift命令
shift [n]
用于将参量列表list 左移指定次数,缺省为左移一次。
参量列表list一旦被移动,最左端的那个参数就从列表中删除。while 循环遍历位置参量列表时,常用到shift
./doit.sh a b c d e f g h
./shfit.sh a b c d e f g h
实例:
while [ $# -gt 0 ] # or (( $# > 0 ))
do
echo $*
shift
done
until [ -z "$1" ] ;do
echo "$1"
shift
done
echo
二、函数
先声明后使用
return :函数中遇到return时就退出,后续的带码将不执行;返回0(默认),1或者某种运算的结果
set # 查看所有函数
declare -f func_name # 查看指定函数
declare -x #所有的环境变量
1、函数介绍
函数function是由若干条shell命令组成的语句块,实现代码重用和模块化编程
它与shell程序形式上是相似的,不同的是它不是一个单独的进程,不能独立运行,而是shell程序的一部分
函数和shell程序比较相似,区别在于:
Shell程序在子Shell中运行
而Shell函数在当前Shell中运行。因此在当前Shell中,函数可以对shell中变量进行修改
2、定义函数
函数=函数名+函数体
function func_name {
函数体
}
function func_name () {
函数体
}
func_naem () {
函数体
}
3、函数使用
函数的定义和使用:
可在交互式环境下定义函数
可将函数放在脚本文件中作为它的一部分
可放在只包含函数的单独文件中
调用:函数只有被调用才会执行
调用:给定函数名
函数名出现的地方,会被自动替换为函数代码
函数的生命周期:被调用时创建,返回时终止
4、函数返回值
函数的执行结果返回值:
(1) 使用echo等命令进行输出
(2) 函数体中调用命令的输出结果
函数的退出状态码:
(1) 默认取决于函数中执行的最后一条命令的退出状态码
(2) 自定义退出状态码,其格式为:return 从函数中返回,用最后状态命令决定返回值
return 0 无错误返回。
return 1-255 有错误返回
5、载入函数
函数的使用必须在脚本最前面引入
. func_name
使用set命令显示所有载入的函数
函数到的执行只用写函数名即可
6、删除函数
unset func_name # 在输入set时将不会显示该函数
环境函数:
声明:export -f function_name
查看:export -f 或者 declare -xf
7、函数变量:避免混乱
local
declare -i num # 将num定义成局部变量
declare -ig num # 在函数中将num定义成全局变量
全局变量
本地变量
局部变量
8、函数可接受参数
var=func_name # 可调用函数的结果
位置变量 $0 在这里不能用,返回的依然是脚本名
$* : 一个整体
$@ : 单个字符串
9、action
action "xxxxxx" :# 成功(:表示true) 后面可跟一个判断,只要结果为真即可
action "cccccc" /bin/false # 只要后面的判断时错的即返回失败
is_true() # yes判断
显示进程树:ps -eHF
10 实例
#!/bin/bash
fact (){
if [[ $1 -eq 0 || $1 -eq 1 ]];then
echo 1
else
echo $[$1*$(fact $[$1-1])] # $[] 进行计算得出值 ;$() 获取函数的返回值
fi
}
fact $1
三、数组
统计时间:time bash a.sh
declare -a # 查看所有数组
如果是关联数组必须先声明,才能使用declare -A arry
关联数组
可自定义索引
创建数组
引用数组的长度
${#arry[*]}
${#arry[@]}
遍历数组所有元素
for i in `seq $[${#filename[@]}-1]`;do echo "the filename is $";done
向数组中追加元素
filename[${#filename[*]}]=xxx
数组切片
$
offset:要跳过的元素个数
number:要取出的元素个数
$ # 取出偏移量之后的所有元素
echo $ # 跳过2个取1个
四、高级字符串操作
${#var}:返回字符串变量var的长度
$:返回字符串变量var中从第offset个字符后(不包括第offset个字符)的字符开始,到最后的部分,offset的取值在0 到${#var}-1 之间(bash4.2后,允许为负值)
$:返回字符串变量var中从第offset个字符后(不包括第offset个字符)的字符开始,长度为number的部分
$:取字符串的最右侧几个字符
注意:冒号后必须有一空白字符
$:从最左侧跳过offset字符,一直向右取到距离最右侧lengh个字符之前的内容
$:先从最右侧向左取到length个字符开始,再向右取到距离最右侧offset个字符之间的内容
注意:-length前空格
1、基于模式取子串
$:其中word可以是指定的任意字符
功能:自左而右,查找var变量所存储的字符串中,第一次出现的word, 删除字符串开头至第一次出现的word及其之前的所有字符
$:同上,贪婪模式,不同的是,删除的是字符串开头至最后一次由word指定的字符及其之前的所有内容
示例:
file="var/log/messages"
$: log/messages
$: messages
$:其中word可以是指定的任意字符;
功能:自右而左,查找var变量所存储的字符串中,第一次出现的word, 删除字符串最后一个字符向左至第一次出现word字符及其之后的所有字符;
file="/var/log/messages"
$: /var/log
$:同上,只不过删除字符串最右侧的字符向左至最后一次出现word字符之间的所有字符;
示例:
$80
$http
2、查找替换
$:查找var所表示的字符串中,第一次被pattern所匹配到的字符串,以substr替换之
$: 查找var所表示的字符串中,所有能被pattern所匹配到的字符串,以substr替换之
$:查找var所表示的字符串中,行首被pattern所匹配到的字符串,以substr替换之
$:查找var所表示的字符串中,行尾被pattern所匹配到的字符串,以substr替换之
3、查找并删除
$:删除var所表示的字符串中第一次被pattern所匹配到的字符串,如果Parttern中包含/需要转义
$:删除var所表示的字符串中所有被pattern所匹配到的字符串
$:删除var所表示的字符串中所有以pattern为行首所匹配到的字符串
$:删除var所表示的字符串中所有以pattern为行尾所匹配到的字符串
4、字符大小写转换
$:把var中的所有小写字母转换为大写
$:把var中的所有大写字母转换为小写
五、高级变量
1、变量赋值
=========================================================================================
|| 变量赋值方式 | 变量y没有设置 变量y为空值 变量yshezho |
| x=$ | x=新值 x=空 x=$y |
|| x=$ | x=新值 x=新值 x=$y |
|----------------|---------------------------------------------------------------------|
|| x=$ | x=空 x=新值 x=新值 |
| x=$ | x=空 x=空 x=新值 |
|-----------------|---------------------------------------------------------------------|
| x=$ | x=新值 x=空 x=$y |
|| | y=新值 y值不变 y值不变 |
|----------------|---------------------------------------------------------------------|
|| x=$ | x=新值 x=新值 x=$y |
| | y=新值 y=新值 y值不变 |
|-----------------|---------------------------------------------------------------------|
| x=$ | 新值输出到标准错误输出 x=空 x=$y |
|| x=$ | 新值输出到标准错误输出 新值输出到标准错误输出 x=$y |
||======================================================================================|
Shell变量一般是无类型的,但是bash Shell提供了declare和typeset两个命令用于指定变量的类型,两个命令是等价的
declare [选项] 变量名
-r 声明或显示只读变量
-i 将变量定义为整型数
-a 将变量定义为数组
-A 将变量定义为关联数组
-f 显示此脚本前定义过的所有函数名及其内容
-F 仅显示此脚本前定义过的所有函数名
-x 声明或显示环境变量和函数
-l 声明变量为小写字母declare –l var=UPPER
-u 声明变量为大写字母declare –u var=lower
eval命令将会首先扫描命令行进行所有的置换,然后再执行该命令。该命令适用于那些一次扫描无法实现其功能的变量.该命令对变量进行两次扫描
示例:
[root@server~]# CMD=whoami
[root@server ~]# echo $CMD
whoami
[root@server ~]# eval $CMD
root
[root@server~]# n=10
[root@server~]# echo
[root@server~]# evalecho
0 1 2 3 4 5 6 7 8 9 10
间接变量引用
如果第一个变量的值是第二个变量的名字,从第一个变量引用第二个变量的值就称为间接变量引用
variable1的值是variable2,而variable2又是变量名,
variable2的值为value,间接变量引用是指通过variable1获得变量值value的行为
variable1=variable2
variable2=value
间接变量引用
bash Shell提供了两种格式实现间接变量引用
eval tempvar=\$$variable1
tempvar=${!variable1}
示例:
[root@server ~]# N=NAME
[root@server ~]# NAME=wangxiaochun
[root@server ~]# N1=${!N}
[root@server ~]# echo $N1
wangxiaochun
[root@server ~]# eval N2=\$$N
[root@server ~]# echo $N2
wangxiaochun
创建临时文件
mktemp命令:创建并显示临时文件,可避免冲突
mktemp[OPTION]... [TEMPLATE]
TEMPLATE: filename.XXX
X至少要出现三个
OPTION:
-d: 创建临时目录
-p DIR或--tmpdir=DIR:指明临时文件所存放目录位置
示例:
mktemp/tmp/test.XXX
tmpdir=`mktemp–d /tmp/testdir.XXX`
mktemp--tmpdir=/testdirtest.XXXXXX
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
示例:
install -m 700 -o wang -g admins srcfile desfile
install –m –d /testdir/installdir
echo $- # - 一个变量
领取专属 10元无门槛券
私享最新 技术干货