bash脚本编程之—函数
bash脚本编程之函数 函数:关键字 function f_name { 函数体 } f_name() { 函数体 } 函数是做什么的,为什么要使用!!! (1) 模块化编程;实现代码重用 (2) 代码结构更清晰,仍然是模块化编程的一个表现而已 变量类型:本地,环境,局部,特殊,位置这些变量! 一,局部变量 局部变量:函数生命周期,函数上下文 local V_NAME=VALUE 比如说:local描述,在其他全局中只要使用local,函数是不会发生变化的 #!/bin/bash # declare -i sum=0 sum() { local sum=0 sum=$[$1+$2] echo $sum } sum 5 6 echo $sum 了解函数递归: 函数直接或间接调用函数本身; 斐波那契数列: 1 1 2 3 5 8 13 从1开始,前两个数各是1,从第三个数开始,每一个数都是前两个数之和,这便是斐波那契数列。 阶乘:n!=n*(n-1)!=n*(n-1)*(n-2)! #!/bin/bash # fact() { if [ $1 -eq 0 -o $1 -eq 1 ]; then echo 1 else echo $[$1*$(fact $[$1-1])] fi } fact 4 数组:变量整列,通过同一个名字进行存取操作 第一个关键词:连续的多个独立的内存空间(元素),每个内存空间相当于一个变量; 数组元素:数组名[索引] 索引:从0开始编号 二:声明数组: declare -a Array_Name bash的属组支持稀疏格式 如何完成元素数组赋值: 方法1,一次赋值一个元素 a_name[index]-value 比如: weekday[0]-"Sunday" weekday[1]-"Monday" 方法2,一次赋值全部元素 weekday=(“Sunday”,"Monday","Tuserady") [root@www ~]# weekday=("SUN" "TUE" "MED") [root@www ~]# echo ${weekday[1]} TUE [root@www ~]# echo ${weekday[0]} SUN [root@www ~]# echo ${weekday[2]} MED [root@www ~]# 方法3,指定索引进行赋值 weekdays-([0]-"Sunday" [3]-"Thu" [6]-"Sat") [root@www ~]# echo ${weekdays[0]} Sunday [root@www ~]# weekdays=([6]="Sat" [4]="Fri" [1]="Mon") [root@www ~]# echo ${weekdays[1]} Mon [root@www ~]# echo ${weekdays[4]} Fri [root@www ~]# echo ${weekdays[6]} Sat [root@www ~]# 方法4, -a 切割后保存在多个元素中 引用数组元素:${array_name[index]} [root@www ~]# read -a mark a b c [root@www ~]# echo ${mark[1]} b [root@www ~]# echo ${mark[2]} c [root@www ~]# echo ${mark[0]} a [root@www ~]# 获取数组长度:${#array[*]},${#array[@]} 既数组中元素的个数; 元素个数 [root@www ~]# echo ${#mark[*]} 3 [root@www ~]# 示例一: 生成是个随机数,保存至数据中,而后显示属组索引为偶数的元素的值 [root@www ~]# echo $RANDOM:生成随机数 [root@www ~]# vim linuxEA.sh #!/bin/bash # for ((i=0;i<10;i++));do rand[$i]=$RANDOM echo ${rand[$i]} #随机数 done echo "=========================" for i in `seq 0 2 9`;do echo ${rand[$i]} done 示例二:定义一个属组,数据元素为/var/log目录下所有以.log结尾的文件的名字;显示每个文件的行数 [root@www ~]#vim Linux.sh #!/bin/bash # declare -a files files=(/var/log/*.log) #取长度 for i in `seq 0 $[${#files[*]}-1]`;do #行数 wc -l ${files[$i]} done [root@www ~]# bash linuxea.sh 81 /var/log/anaconda.ifcfg.log 255 /var/log/anaconda.log 396 /var/log/anaconda.program.log 1341 /var/log/anaconda.storage.log 811 /var/log/anaconda.yum.log 53 /var/log/boot.log 1807 /var/log/dracut.log 59 /var/log/mysqld.log 2 /var/log/pm-powersave.log 0 /var/log/spice-vdagent.log 0 /var/log/wpa_supplicant.log 693 /var/log/Xorg.0.log 97 /var/log/yum.log [root@www ~]# 三:数组切片 数组切片:从数组中挑选出指定的某个或某些元素 ${array[@]:offset:number} 1,offset:偏移的元素的个数; number:要取出的元素的个数 [root@www ~]# weekdays=("Sun" "Mon" "Tue" "Wed" "Thu" "Fri" "Sat") 取周二和周三,@偏移两个取两个 [root@www ~]# echo ${weekdays[@]:2:2} Tue Wed [root@www ~]# 偏移两个取剩下所有 [root@www ~]# echo ${weekdays[@]:2} Tue Wed Thu Fri Sat [root@www ~]# 2,${array[@]:offset:} 取出偏移量之后剩余的所有的元素 ${array[@]}取所有 [root@www ~]# echo ${weekdays[@]} Sun Mon Tue Wed Thu Fri Sat [root@www ~]# 3,从数组中追加元素: 稀疏格式追加+1是不可以的 [root@www ~]# hello=([0]"abc" [1]="mn" [6]="hi") [root@www ~]# echo ${#hello[*]} 3 [root@www ~]# [root@www ~]# hello=([0]"abc" [1]="mn" [2]="hi") [root@www ~]# hello[${#hello[*]}]="MARK" [root@www ~]# echo ${hello[@]} [0]abc mn hi MARK [root@www ~]# hello[${#hello[*]}]="HOW ARE YOU" [root@www ~]# echo ${hello[@]} [0]abc mn hi MARK HOW ARE YOU [root@www ~]# hello[${#hello[*]}]="is LinuxEA.com " [root@www ~]# echo ${hello[@]} [0]abc mn hi MARK HOW ARE YOU,is LinuxEA.com 4,从数组中删除元素: 不需要加$ unset array[index] 切除hello的第0个元素 [root@www ~]# unset hello[0] [root@www ~]# echo ${hello[*]} mn hi MARK HOW ARE YOU,is LinuxEA.com [root@www ~]# 5,bash从4.0版本之后开始支持关联数组: 数组索引可为自定义的任何字符串, 定义方法:declare -A array_Name [root@www ~]# declare -A wdays [root@www ~]# wdays=([sun]="Sunday" [mon]="Monday" [tue]="Tuesday") [root@www ~]# echo ${wdays[sun]} Sunday [root@www ~]# 四:bash的字符串处理机制: bash的字符串处理机制: 1, 字符串切片:${var:offset:lenth} [root@www ~]# mypath="/etc/sysconfig/network-scripts/" 取基名,先取5个 [root@www ~]# echo ${mypath:5} sysconfig/network-scripts/ 再取15个 [root@www ~]# echo ${mypath:15} network-scripts/ 15个之后再取 [root@www ~]# echo ${mypath:15:5} netwo [root@www ~]# 2, 取出字符的最后几个字符:${var: -length} [root@www ~]# mypath="/etc/sysconfig/network-scripts" 取最后一个/线 [root@www ~]# echo ${mypath##*/} network-scripts [root@www ~]# 3, 基于模式取字串: ${var*word}:自左而右,查找var变量中存储的字符串中第一次出现的有word所指明的字符,删除此字符及其左侧的所有内容 ${var##*word}:自左而右,查找var变量中存储的字符串中最后一次出现的有word所指明的字符,删除此字符及其左侧的所有内容 ${var%word*} :自右而左,查找var变量中存储的字符串中第一次出现的有word所指明的字符,删除此字符及其右侧的所有内容 ${var%%word*}:自右而左,查找var变量中存储的字符串中最后一次出现的有word所指明的字符,删除此字符及其右侧的所有内容 4, 如果scripts后面有/线,在自左而右找第一次/出现的位置,所有就删空了 [root@www ~]# mypath="/etc/sysconfig/network-scripts/" [root@www ~]# echo ${mypath##*/} [root@www ~] 如果换成C,就从/etc/sysconfig/network-s开始 [root@www ~]# echo ${mypath##*c} ripts/ 如果换成一个#号,那就是第一次出现C的时候 [root@www ~]# echo ${mypath#*c} /sysconfig/network-scripts/ [root@www ~]# %号是反过来的 自右而左找第一次c出现的位置,并删除字符右侧的所有内容 [root@www ~]# echo ${mypath%c*} /etc/sysconfig/network-s [root@www ~]# 自右而左找最后一次c出现的位置 [root@www ~]# echo ${mypath%%c*} /et [root@www ~]# 5, 取指定路径的目录名: 自右而左查找第一次出现/,删除/右侧的内容 [root@www ~]# mypath="/etc/sysconfig/network-scripts" [root@www ~]# echo ${mypath%/*} /etc/sysconfig [root@www ~]# 示例: [root@www ~]# url="httpd://www.linuxea.com:80" 取端口 [root@www ~]# echo ${url##*:} 80 [root@www ~]# 取协议: [root@www ~]# echo ${url%%:*} httpd [root@www ~]# 五:查找替换: 查找替换: ${var/pattern/replacement}:查找var变量存储的字符中第一次由pattern匹配到的内容,并替换为replacement; ${var//pattern/replacement}:查找var变量存储的字符中所有能够由pattern匹配到的内容,并替换为replacement; ${var/#pattern/replacement}:查找var变量存储的字符中最开始处能够由pattern匹配到的内容,并替换为replacement; ${var/%pattern/replacement}:查找var变量存储的字符中最后位置能够由pattern匹配到的内容,并替换为replacement; 1, [root@www ~]# echo ${url/com/org} httpd://www.linuxea.org:80 [root@www ~]# 2, 替换所有替换:${var//pattern/replacement} [root@www ~]# echo ${url//w/W} httpd://WWW.linuxea.com:80 [root@www ~]# 3, [root@www ~]# userinfo="root:x:0:0:root user:/root:/bin/bash/root" [root@www ~]# echo ${userinfo/root/ROOT} ROOT:x:0:0:root user:/root:/bin/bash [root@www ~]# echo ${userinfo/#root/ROOT} ROOT:x:0:0:root user:/root:/bin/bash [root@www ~]# echo ${userinfo/%root/ROOT} root:x:0:0:root user:/root:/bin/bash [root@www ~]# echo ${userinfo/%root/ROOT} root:x:0:0:root user:/root:/bin/bash/ROOT [root@www ~]# echo ${userinfo//root/ROOT} ROOT:x:0:0:ROOT user:/ROOT:/bin/bash/ROOT [root@www ~]# 六:查找删除: 查找删除 ${var/pattern}:查找var变量存储的字符中第一次由pattern匹配到的内容,并删除; ${var//pattern}:查找var变量存储的字符中所有能够由pattern匹配到的内容,并删除; ${var/#pattern}:查找var变量存储的字符中最开始处能够由pattern匹配到的内容,并删除; ${var/%pattern}:查找var变量存储的字符中最后位置能够由pattern匹配到的内容,并删除; 1,删除第一此出现的root [root@www ~]# echo ${userinfo/root} :x:0:0:root user:/root:/bin/bash/root 2,删除整个行的root [root@www ~]# echo ${userinfo//root} :x:0:0: user:/:/bin/bash/ [root@www ~]# 3,删除行首root [root@www ~]# echo ${userinfo/#root} :x:0:0:root user:/root:/bin/bash/root 4,删除行尾root [root@www ~]# echo ${userinfo/%root} root:x:0:0:root user:/root:/bin/bash/ [root@www ~]# 七:字符串大小写转换: 字符串大小写转换 1, ${var^^}:把var变量中的所有小写字母,统统替换为大写; [root@www ~]# echo ${userinfo^^} ROOT:X:0:0:ROOT USER:/ROOT:/BIN/BASH/ROOT [root@www ~]# 2, ${var,,}:把var变量中的所有大写字母,统统替换为小写; [root@www ~]# myinfo=${userinfo^^} [root@www ~]# echo $myinfo ROOT:X:0:0:ROOT USER:/ROOT:/BIN/BASH/ROOT [root@www ~]# echo ${myinfo,,} root:x:0:0:root user:/root:/bin/bash/root [root@www ~]# 八:变量赋值: 变量赋值 1,${var:-word}:如果变量var为空或未声明,则返回word所表示的字符串;否则,则返回var变量的值; 2,${var:=word}:如果变量var为空或未声明,则返回word所表示的字符串,并且把word赋值为var变量;否则,则返回var变量的值; 3,${var:?error}:如果变量var为空或未声明,则返回error为错误信息;否则,则返回var变量的值; 4,${var:+word}:如果变量var为空或未声明,忽略;否则,则返回word; [root@www ~]# echo $name [root@www ~]# echo ${name:-tom} tom [root@www ~]# name=mark [root@www ~]# echo ${name:-tom} mark [root@www ~]# 撤销掉name 。 1,为了避免把原有值给替换掉 [root@www ~]# unset name [root@www ~]# name=${name:-tom}:如果name原来有值,它把自己值赋给自己,如果没有赋,则赋给name [root@www ~]# echo $name tom [root@www ~]# name=${name:-jerry} :name已经有值为tom [root@www ~]# echo $name:仍然显示tom,因为name在第一次时已经赋值 tom [root@www ~]# 2, [root@www ~]# unset name [root@www ~]# echo "User's is ${name:=tom}":等于。 User's is tom [root@www ~]# echo "User's name is ${name:=tom}" User's name is tom [root@www ~]# echo $name tom [root@www ~]# [root@www ~]# unset name [root@www ~]# echo "User's name is ${name:-tom}":-号是不会赋值的只会返回 User's name is tom [root@www ~]# echo $name [root@www ~]# [root@www ~]# unset name [root@www ~]# echo "User's name is ${name:?wrong}" -bash: name: wrong [root@www ~]# name=tom [root@www ~]# echo "User's name is ${name:?wrong}" User's name is tom [root@www ~]# 如果对应的变量没有值,我们要直接引用的话,命令是不会正常运行的。 [root@www ~]# unset name [root@www ~]# echo "User's name is ${name:?wrong}" -bash: name: wrong [root@www ~]# echo $? 1 [root@www ~]# 但是在有些场景下它还是有用的