一、函数: 1.概述:Shell函数类似于Shell脚本,里面存放了一系列的指令,不过Shell的函数存在于内存,而不是硬盘文件,所以速度很快,另外,Shell还能对函数进行预处理,所以函数的启动比脚本更快。shell允许将一组命令集或语句形成一个可用块,这些块称为shell函数。 2.语法: function 函数名() { 语句 [return] } 解析:所有函数在使用前必须定义。这意味着必须将函数放在脚本开始部分,直至shell解释器首次发现它时,才可以使用。调用函数仅使用其函数名即可。函数中的关键字“return”可以放到函数体的任意位置,通常用于返回某些值,Shell在执行到return之后,就停止往下执行,返回到主程序的调用行,return的返回值只能是0~256之间的一个整数,返回值将保存到变量“$?”中。 3.shell函数的退出及删除: 函数结束之后会返回调用函数的部分继续执行, 退出函数体:exit退出整个脚本、break语句来中断函数的执行。 shell中查询函数及删除: source或. 脚本 ##将函数载入到内存 declare -f ##可以显示定义的函数内容 declare -F ##可以只显示定义的函数名 unset -f ##可以从Shell内存中删除函数 4.变量: 5.案例: 案例一:函数的基本使用 [root@localhost ~]# vi func_linuxfan.sh #!/bin/bash read -p "输入第一个数:" ANum function linuxfan(){ echo "这个函数的功能是两个数进行相加:" read -p "输入第二个数:" BNum echo "您输入的数是$ANum和$BNum! " SUM=$(expr $ANum + $BNum) echo "两个数相加的结果是:$SUM" local A="哈哈!" echo "\$A是使用了local声明的局部变量,在函数体内情况是:$A" echo "\$ANum是在函数体外的变量,函数体内调用它的情况是:$ANum" return 0 ##设置返回值 } linuxfan ##调用函数 echo "\$A 在函数体外,结果是这样的:$A" echo "\$BNum 在函数体外,结果是这样的:$BNum" :wq [root@localhost ~]# chmod +x func_linuxfan.sh [root@localhost ~]# ./func_linuxfan.sh 输入第一个数:123 这个函数的功能是两个数进行相加: 输入第二个数:456 您输入的数是123和456! 两个数相加的结果是:579 $A是使用了local声明的局部变量,在函数体内情况是:哈哈 $ANum是在函数体外的变量,函数体内调用它的情况是:123 $A 在函数体外,结果是这样的: $B 在函数体外,结果是这样的: [root@localhost ~]# source func_linuxfan.sh ##从脚本文件中载入函数 [root@localhost bin]# declare -f ##显示当前shell中函数内容 linuxfan () { 省略函数体内的内容。 } [root@localhost bin]# declare -F ##查看当前shell中函数名称 declare -f linuxfan [root@localhost bin]# unset -f linuxfan ##删除当前shell中的函数 [root@localhost bin]# declare -F ##查看验证 案例二:函数参数的传递 函数可以通过位置变量传递参数。 函数名 参数1 参数2 参数3 参数4 ... [root@localhost ~]# vi fun-paramters.sh #!/bin/bash funparam(){ echo "\$1可以给函数传递第一个参数,函数的第一个参数:$1" echo "\$2可以给函数传递第二个参数,函数的第二个参数:$2" echo "\$7可以给函数传递第七个参数,函数的第七个参数:$7" echo "\${10}可以给函数传递第十个参数,函数的第十个参数:${10}" echo "\${11}可以给函数传递第十一个参数,函数的第十一个参数:${11}" echo "函数有$#个参数,函数参数具体内容是$*" } funparam 1 2 3 4 5 6 11 8 9 66 99 echo "脚本后的参数\$1是$1;" echo "脚本后的参数\$2是$2;" echo "脚本后的参数\$3是$3;" echo "脚本后的参数\$4是$4;" echo "脚本后的参数\$5是$5;" :wq [root@localhost ~]# chmod +x fun-paramters.sh [root@localhost ~]# ./fun-paramters.sh a b c d f e $1可以给函数传递第一个参数,函数的第一个参数:1 $2可以给函数传递第一个参数,函数的第一个参数:2 $7可以给函数传递第一个参数,函数的第一个参数:11 ${10}可以给函数传递第一个参数,函数的第一个参数:66 ${11}可以给函数传递第一个参数,函数的第一个参数:99 函数有11个参数,函数参数具体内容是1 2 3 4 5 6 11 8 9 66 99 脚本后的参数\$1是a; 脚本后的参数\$1是b; 脚本后的参数\$1是c; 脚本后的参数\$1是d; 脚本后的参数\$1是f; [root@localhost ~]# cat test.sh ##将shell命令行中的参数传递给函数 #!/bin/bash function test(){ echo "$1 $2 $3" } test $* [root@localhost ~]# ./ test.sh a b c a b c 案例三: 扩展学习(更多练习): 向系统学习函数的使用: http://www.cnblogs.com/image-eye/archive/2011/10/26/2220405.html ##请大家阅读/etc/init.d/funcations详解,至少搞懂daemon和killproc两个函数的作用。然后静下心来阅读这个脚本,并给它添加注释你能学会很多东西: [root@localhost ~]# cat /etc/init.d/vsftpd ##这是vsftpd的启动脚本,非常经典 #!/bin/bash # ### BEGIN INIT INFO # Provides: vsftpd # Required-Start: $local_fs $network $named $remote_fs $syslog # Required-Stop: $local_fs $network $named $remote_fs $syslog # Short-Description: Very Secure Ftp Daemon # Description: vsftpd is a Very Secure FTP daemon. It was written completely from # scratch ### END INIT INFO # vsftpd This shell script takes care of starting and stopping # standalone vsftpd. # # chkconfig: - 60 50 # description: Vsftpd is a ftp daemon, which is the program \ # that answers incoming ftp service requests. # processname: vsftpd # config: /etc/vsftpd/vsftpd.conf # Source function library. . /etc/rc.d/init.d/functions # Source networking configuration. . /etc/sysconfig/network RETVAL=0 prog="vsftpd" start() { # Start daemons. # Check that networking is up. [ ${NETWORKING} = "no" ] && exit 1 [ -x /usr/sbin/vsftpd ] || exit 1 if [ -d /etc/vsftpd ] ; then CONFS=`ls /etc/vsftpd/*.conf 2>/dev/null` [ -z "$CONFS" ] && exit 6 PROC_FAILED=0 for i in $CONFS; do site=`basename $i .conf` echo -n $"Starting $prog for $site: " daemon /usr/sbin/vsftpd $i RETVAL=$? echo if [ $RETVAL -eq 0 ] && [ ! -f /var/lock/subsys/$prog ]; then touch /var/lock/subsys/$prog elif [ $RETVAL -ne 0 ]; then ps -FC vsftpd | grep "$i" > /dev/null RETVAL=$? if [ $PROC_FAILED -eq 0 ] && [ $RETVAL -ne 0 ]; then PROC_FAILED=1 fi fi done if [ $RETVAL -eq 0 ] && [ $PROC_FAILED -ne 0 ]; then RETVAL=1 fi else RETVAL=1 fi return $RETVAL } stop() { # Stop daemons. echo -n $"Shutting down $prog: " killproc $prog RETVAL=$? echo [ $RETVAL -eq 0 ] && rm -f /var/lock/subsys/$prog return $RETVAL } # See how we were called. case "$1" in start) start ;; stop) stop ;; restart|reload) stop start RETVAL=$? ;; condrestart|try-restart|force-reload) if [ -f /var/lock/subsys/$prog ]; then stop start RETVAL=$? fi ;; status) status $prog RETVAL=$? ;; *) echo $"Usage: $0 {start|stop|restart|try-restart|force-reload|status}" exit 1 esac exit $RETVAL 案例四:测试主机访问url路径 二、shell数组: 1.概述:数组就是一组数据类型相同集合; 2.数组的定义及使用: [root@localhost bin]# arr1=() ##定义空元素数组 [root@localhost bin]# arr2=(1 2 3 4 5 6) ##定义数字元素的数组 [root@localhost bin]# arr3=("有梦想" "向往远方和诗" "高薪就业" "静心沉迷于学习!") ##定义字符串元素的数组,注意用引号(单、双引号皆可) [root@localhost bin]# echo ${arr2[0]} 1 [root@localhost bin]# echo ${arr2[3]} 4 [root@localhost bin]# echo ${arr3[3]} 静心沉迷于学习! [root@localhost bin]# echo ${arr3[*]} 有梦想 向往远方和诗 高薪就业 静心沉迷于学习! [root@localhost bin]# for i in ${arr3[*]};do echo $i;done 有梦想 向往远方和诗 高薪就业 静心沉迷于学习! [root@localhost bin]# echo ${#arr3[*]} ##获取数组的长度 4 [root@localhost bin]# echo ${#arr3[@]} 4 数组赋值格式:数组名[下标]=值,如果下标不存在,则新增数组元素; 下标已有,则覆盖值。 [root@localhost bin]# echo ${arr2[*]} ##获取数组所有元素 1 2 3 4 5 6 [root@localhost bin]# arr2[6]=8 ##下标为6(第七个)的内容为8,添加元素 [root@localhost bin]# echo ${arr2[*]} ##验证 1 2 3 4 5 6 8 [root@localhost bin]# arr2[2]=8 ##修改下标为2的元素为8,覆盖原有值 [root@localhost bin]# echo ${arr2[*]} ##验证 1 2 8 4 5 6 8 数组分片的格式:${数组名[*或@]:起始位:长度},截取部分数组,返回字符串,中间用空格分隔;将结果使用“()”,则得到新的切片数组。 [root@localhost bin]# echo ${#arr3[*]} 4 [root@localhost bin]# echo ${arr3[*]:0:1} 有梦想 [root@localhost bin]# echo ${arr3[*]:2:2} 高薪就业 静心沉迷于学习! [root@localhost bin]# arr4=(${arr3[*]:2:2}) [root@localhost bin]# echo ${arr4[*]} 高薪就业 静心沉迷于学习! 数组替换元素的格式:${数组名[*或@]/查找字符/替换字符}, 不会修改原数组;如需修改的数组,将结果使用“()”赋给新数组。 [root@localhost bin]# echo ${arr2[*]} 1 2 8 4 5 6 8 [root@localhost bin]# echo ${arr2[*]/4/9} 1 2 8 9 5 6 8 [root@localhost bin]# arr5=${arr2[*]/4/9} [root@localhost bin]# echo ${arr5[*]} 1 2 8 9 5 6 8 删除数组的格式:unset 数组,清除整个数组; unset 数组[下标],清除单个元素。 [root@localhost bin]# echo ${arr3[*]} 有梦想 向往远方和诗 高薪就业 静心沉迷于学习! [root@localhost bin]# unset arr3[0] [root@localhost bin]# echo ${arr3[*]} 向往远方和诗 高薪就业 静心沉迷于学习! [root@localhost bin]# unset arr3 [root@localhost bin]# echo ${arr3[*]} 三、shell当中括号的使用: 1.单小括号(): 命令组:组合多条命令一起执行,并按照顺序执行。 [root@www ~]# (umask 0077;mkdir -p test;ls -ld test) 替换命令:效果等于反撇,在命令中执行命令,并将执行结果交给命令处理。 [root@www ~]# rpm -qf $(which convert) ##查询命令的安装包 ImageMagick-6.5.4.7-6.el6_2.x86_64 用于初始化数组:如array=(a b c d) [root@www ~]# array=(a b c d) 2.双小括号(()) 计算其他进制(二、八、十六)的数到十进制: [root@www ~]# echo $((2#11)) ##二转十 3 [root@www ~]# echo $((8#11)) ##八转十 9 [root@www ~]# echo $((16#11)) ##十六转十 17 [root@www ~]# echo $((16#1f)) 31 [root@localhost bin]# echo $((3+2)) ##加减乘除取摸运算 5 [root@localhost bin]# echo $((3-2)) 1 [root@localhost bin]# echo $((3*2)) 6 [root@localhost bin]# echo $((3/2)) 1 [root@localhost bin]# echo $((3%2)) 1 重新定义变量: [root@www ~]# a=5;((a++));echo $a 6 算术运算比较,双括号内的变量可以不使用$,表达式用分号分开: [root@www ~]# for i in {0..4};do echo $i;done [root@www ~]# for i in $(seq 0 4);do echo $i;done [root@www ~]# for ((i=0;i<5;i++));do echo $i;done ##上述三种都是一样的效果 [root@www ~]# i=10 [root@www ~]# if ((i>5));then echo $i;fi [root@www ~]# if [ $i -gt 5 ];then echo $i;fi ##两个if的效果相同 3.中括号[ ] 条件表达式 [root@www ~]# [ -f /etc/hosts ]&&echo ok [root@www ~]# test -f /etc/hosts &&echo ok 字符范围。用作正则表达式的一部分,描述一个匹配的字符范围。 [root@www ~]# i=1 ##case中使用的[0-9]|[a-z]|[A-Z]表示正则 [root@www ~]# case $i in [0-9]) echo "number"; ;; [a-z]|[A-Z]) echo "alph"; ;; esac 4.双中括号[[ ]] ①[[是 bash 程序语言的关键字。并不是一个命令,[[ ]] 结构比[ ]结构更加通用。在[[和]]之间所有的字符都不会发生文件名扩展或者单词分割,但是会发生参数扩展和命令替换。 ②支持字符串的模式匹配,使用=~操作符时甚至支持shell的正则表达式。字符串比较时可以把右边的作为一个模式,而不仅仅是一个字符串,比如[[ hello == hell? ]],结果为真。[[ ]] 中匹配字符串或通配符,不需要引号。 ③使用[[ ... ]]条件判断结构,而不是[ ... ],能够防止脚本中的许多逻辑错误。比如,&&、||、<和> 操作符能够正常存在于[[ ]]条件判断结构中,但是如果出现在[ ]结构中的话,会报错。比如可以直接使用if [[ $a != 1 && $a != 2 ]], 如果不使用双括号, 则为if [ $a -ne 1] && [ $a != 2 ]或者if [ $a -ne 1 -a $a != 2 ]。 [root@www ~]# a=3 [root@www ~]# if [ $a != 1 && $a != 2 ];then echo $a;fi ##报错 -bash: [: missing `]' [root@www ~]# if [[ $a != 1 && $a != 2 ]];then echo $a;fi ##成功执行 3 [root@www ~]# if [ $a != 1 ] && [ $a != 2 ];then echo $a;fi ##执行成功 3 5.花括号{ } 常规用法: [root@www ~]# touch {a..z}.mp{3..5} ##..表示分割顺序文件列表 [root@www ~]# ls {{a..e},h,y,z}.mp4 a.mp4 b.mp4 c.mp4 d.mp4 e.mp4 h.mp4 y.mp4 z.mp4 定义函数:代码块,又被称为内部组,这个结构事实上创建了一个匿名函数 。与小括号中的命令不同,花括号内的命令不会新开一个子shell运行,即脚本余下部分仍可使用括号内变量。 字符串提取和替换: ${var:num},${var:num1:num2},${var/pattern/pattern},${var//pattern/pattern} 第一种模式:${var:num},这种模式时,shell在var中提取第num个字符到末尾的所有字符。若num为正数,从左边0处开始;若num为负数,从右边开始提取字串,但必须使用在冒号后面加空格或一个数字或整个num加上括号,如${var: -2}、${var:1-3}或${+var:(-2)}。 [root@www ~]# var=www.linuxfan.cn [root@www ~]# echo ${var:4} linuxfan.cn [root@www ~]# echo ${var:(-2)} cn 第二种模式:${var:num1:num2},num1是位置,num2是长度。表示从$var字符串的第$num1个位置开始提取长度为$num2的子串。不能为负数。 [root@www ~]# var=www.linuxfan.cn [root@www ~]# echo ${var:4:5} linux [root@www ~]# echo ${var:1:3} ww. [root@www ~]# echo ${var:0:3} www 第三种模式:${var/pattern/pattern}表示将var字符串的第一个匹配的pattern替换为另一个pattern。。 [root@www ~]# var=www.linuxfan.cn [root@www ~]# echo ${var/www/dns} dns.linuxfan.cn 第四种模式:${var//pattern/pattern}表示将var字符串中的所有能匹配的pattern替换为另一个pattern。 [root@www ~]# var=www.linuxfan.cn [root@www ~]# echo ${var/n/N} www.liNuxfan.cn [root@www ~]# echo ${var//n/N} www.liNuxfaN.cN 6.多条命令执行 单小括号:(cmd1;cmd2;cmd3)新开一个子shell顺序执行命令cmd1,cmd2,cmd3, 各命令之间用分号隔开, 最后一个命令后可以没有分号。 [root@www tmp]# (touch index.html;rm -rf index.html;ls -l;) 单大括号:{ cmd1;cmd2;cmd3;} 在当前shell顺序执行命令cmd1,cmd2,cmd3, 各命令之间用分号隔开, 最后一个命令后必须有分号, 括号两侧必须有空格。 [root@www tmp]# {touch index.html;rm -rf index.html;ls -l;} ##开始的{后无空格报错 -bash: syntax error near unexpected token `}' [root@www tmp]# { touch index.html;rm -rf index.html;ls -l } [root@www tmp]# { touch index.html;rm -rf index.html;ls -l; } ##最后一条命令必须; 总用量 0 注:对{}和()而言, 括号中的重定向符只影响该条命令,而括号外的重定向符影响到括号中的所有命令。 |
|