shell编程--函数篇

一:函数分类

  1. 本地函数(本地变量)
    local 变量名。本地函数中对变量的修改,赋值只在当前函数运行期间有效。
    func1 () { local name=test;echo "func1:name=$name"; local age=18;echo "func1:age=$age"; echo $$;}
  2. 全局函数(本地变量)
    不加local及declare -i(仅限整数数字) 默认为全局函数,而declare -ig也为全局函数(本地变量)。全局函数对变量的修改及赋值对当前shell均有效。但子Shell不继承
    func1 () {name=test; declare -i age=16; echo "func1:name=$name, func1:age=$age"; }
  3. 环境函数(环境变量)
    declare -xf 环境函数中的变量会对子shell继承 或 export -f

    练习1:使用函数编写脚本,实现打印国际象棋棋盘,要求每个格子由8个空格组成。
    方法一:
    #!/bin/bash
    red() {
            echo -e "\033[41m        \033[0m\c"
    }
    yel() {
            echo -e "\033[43m        \033[0m\c"
    }
    redyel() {
            for ((i=1;i<=4;i++));do
                    for ((j=1;j<=4;j++));do
                            [ "$1" = "-r" ] && { yel;red; } || { red;yel; }
                    done
                    echo
            done
    }

    for ((line=1;line<=8;line++));do
            [ $[$line%2] -eq 0 ] && redyel || redyel -r
    done

    方法二:
    #!/bin/bash
    lvse (){
            echo -e "\e[1;42m        \e[0m\c"
    }
    huangse (){
            echo -e "\e[1;43m        \e[0m\c"
    }
    for i in {1..8};do
            for x in {1..4};do
                    for n in {1..8};do
                            a=`echo $[$[$i+$n]%2]`
                            if [ $a -eq 0 ];then
                                    huangse
                            else
                                    lvse
                            fi
                    done
            echo
            done
    done



二:函数的返回值
    1:return
        0为正确结果
        1-255为错误
    2:exit

0为正确结果
        1-255为错误



三:unset

unset取消函数定义,仅影响当前shell及其子Shell。

练习2:
编写函数,实现OS的版本判断

编写函数,实现取出当前系统eth0的IP地址
编写函数,实现打印绿色OK和红色FAILED
编写函数,实现判断是否无位置参数,如无参数,提示错误

version () {
        ver=$(cat /etc/redhat-release | sed -r "s/.* ([0-9])[.].*/\1/")

echo "当前版本号为 $ver"

return 0

}

ipaddr () {

ip=$(ip a s | grep ens33 | sed -n "2p"| cut -d/ -f1| awk '{print $2}')
        echo $ip

return 0

}

print_color() {
        echo -e "\033[41mFAILED\033[0m"
        echo -e "\033[42mOK\033[0m"
}

judge_canshu() {

if [ $# -eq 0 ];then
                echo "请输入至少一个参数"
        else
                echo "共有 $# 个参数"

fi
}

练习3

在centos5或6上,编写服务脚本/etc/init.d/routed,完成如下要求
(1) 脚本可接受参数:start, stop, restart, status
(2) 如果参数非此四者之一,提示使用格式后报错退出
(3) 如是start:则创建/var/lock/subsys/routed, 并显示“OK”
考虑:如果事先已经启动过一次,则显示routed already runing...
(4) 如是stop:则删除/var/lock/subsys/SCRIPT_NAME, 并显示“OK”
考虑:如果事先已然停止过了,则显示"Faild"
(5) 如是restart,则先stop, 再start
考虑:如果本来没有start,则在stop步骤显示"Faild",而在start步骤显示OK.
(6) 如是status, 则如果/var/lock/subsys/SCRIPT_NAME文件存在,则显示“routed is running...”
如果/var/lock/subsys/SCRIPT_NAME文件不存在,则显示“routed is stopped...”
(7)在所有模式下禁止启动该服务,可用chkconfig 和 service命令管理
(8) 当start该脚本后,会在该主机上配置去往1.1.1.0和2.2.2.0网络的路由去往172.18.0.1.
(9) 当stop该脚本后,会删除(8)的两条路由
(10) 当restart时,会先删除路由,再加上.

#!/bin/bash
# chkconfig: 2345 19 80
# description:routed
if ! [ -d /var/lock/subsys ];then
        mkdir -p /var/lock/subsys &> /dev/null
fi
. /etc/init.d/functions

start () {
        if [ -e /var/lock/subsys/routed ];then
                action "Staring routed: routed already runing" false
        else
                touch /var/lock/subsys/routed
                route add -net 1.1.1.0/24 gw 172.18.0.1
                route add -net 2.2.2.0/24 gw 172.18.0.1
                action "Starting routed:" true
        fi
}
stop () {
        if ! [ -e /var/lock/subsys/routed ];then
                action "Shutting down routed:routed not running" false
        else
                rm -rf /var/lock/subsys/routed
                route del -net 1.1.1.0/24 gw 172.18.0.1
                route del -net 2.2.2.0/24 gw 172.18.0.1
                action "Shutting down routed:" true
        fi
}
status () {
        if [ -e /var/lock/subsys/routed ];then
                echo "routed is running..."
        else
                echo "routed is stopped..."
        fi
}
case $1 in
        start)
                start;;
        stop)
                stop;;

restart)
                stop
                start;;
        status)
                status;;
        *)
                echo "Usage: $0 {start|stop|status|restart} "
esac

练习4

编写脚本/root/bin/copycmd.sh
(1) 提示用户输入一个可执行命令名称
(2) 获取此命令所依赖到的所有库文件列表
(3) 复制命令至某目标目录(例如/mnt/sysroot)下的对应路径下; 如:/bin/bash ==> /mnt/sysroot/bin/bash
    /usr/bin/passwd ==> /mnt/sysroot/usr/bin/passwd
(4) 复制此命令依赖到的所有库文件至目标目录下的对应路径下:  如:/lib64/ld-linux-x86-64.so.2 ==> /mnt/sysroot/lib64/ld-linux-x86-64.so.2
(5)每次复制完成一个命令后,不要退出,而是提示用户键入新的要复制的命令,并重复完成上述功能;直到用户输入quit退出
cpcmd () {
cp `which $1|tail -1` /mnt/sysroot`which $1|tail -1` &> /dev/null
ldd `which $1|tail -1`|egrep -o "/lib64/.*"|sed -r '[email protected]/lib64(/.*) .*@\[email protected]' > /mnt/sysroot/test.txt
while read line
do      
        cd /mnt/sysroot/lib64
        if [ -f $line ];then
                continue
        else    
                cp /lib64$line /mnt/sysroot/lib64$line &> /dev/null
        fi
done < /mnt/sysroot/test.txt
}

#!/bin/bash
. /root/bin/myfunctions
while true;do
read -p " 请输入命令:" cmd
cpcmd $cmd
done

练习5:

编写函数实现两个数字做为参数,返回最大值

max () {
        if [ $1 -ge $2 ];then
                echo "最大值是:$1"
        else
                echo "最大值是:$2"
        fi

练习6:

斐波那契数列又称黄金分割数列,因数学家列昂纳多·斐波那契以兔子繁殖为例子而引入,故又称为“兔子数列”,指的是这样一个数列:0、1、1、2、3、5、8、13、21、34、……,斐波纳契数列以如下被以递归的方法定义:F(0)=0,F(1)=1,F(n)=F(n-1)+F(n-2)(n≥2),利用函数,求n阶斐波那契数列

fei () {
        if [ $1 -eq 0 ];then
                let f$1=0
                echo $f$1
        fi
        if [ $1 -eq 1 ];then
                let f$1=1
                echo $f$1
        fi
        if [ $1 -gt 1 ];then
                echo $[$(fei $[$1-1])+$(fei $[$1-2])]
        fi
}

#!/bin/bash
. /root/bin/myfunctions
for n in `seq $1`
do
        fei $n
done

练习7:    
    汉诺塔(又称河内塔)问题是源于印度一个古老传说。大梵天创造世界的时候做了三根金刚石柱子,在一根柱子上从下往上按照大小顺序摞着64片黄金圆盘。大梵天命令婆罗门把圆盘从下面开始按大小顺序重新摆放在另一根柱子上。并且规定,在小圆盘上不能放大圆盘,在三根柱子之间一次只能移动一个圆盘,利用函数,实现N片盘的汉诺塔的移动步骤
han () {
        if [ $1 -eq 1 ];then
                echo " $2 --> $4"
        else
                han $[$1-1] $2 $4 $3
                echo " $2 --> $4 "
                han $[$1-1] $3 $2 $4
        fi
}

#!/bin/bash  
. /root/bin/myfunctions
han $1 'A' 'B' 'C'



大家也可能发现了,练习六,练习七考察的是递归,在最后我们来介绍一下什么是递归,以及遇到递归的思路是什么。

首先:一定有一种可以退出程序的情况,我们也叫作递归出口。

其次:总是在尝试将一个问题化简到更小的规模。

最后:父问题与子问题不能有重叠的部分

如果满足了这三点。我们就可以利用递归来处理问题了。

原文地址:http://blog.51cto.com/13560258/2089725

时间: 2024-10-11 12:43:43

shell编程--函数篇的相关文章

Shell编程进阶篇(完结)

1.1 for循环语句 在计算机科学中,for循环(英语:for loop)是一种编程语言的迭代陈述,能够让程式码反复的执行. 它跟其他的循环,如while循环,最大的不同,是它拥有一个循环计数器,或是循环变数.这使得for循环能够知道在迭代过程中的执行顺序. 1.1.1 shell中的for循环 shell中的for 循环与在c中不同,它包含三种形式:第一种结构是列表for 循环;第二种结构就是不带列表的for循环:第三种就类似于C语言. ①   列表for循环(常用) #!/bin/bash

shell编程函数与数组

1.shell中函数 (1)shell中函数的语法 语法一: 函数名(){ 指令 return n } 语法二: function 函数名(){ 指令 return n } (2)shell中函数的调用执行 1)直接执行函数名即可,在执行函数时,不要带小括号,函数定义及函数体必须要在执行的函数名前定义. 2)带参数的函数的执行方法:函数名  参数1  参数2 (3)函数带参数的说明 1)在函数体重,位置函数都可以是函数的参数 2)父脚本的参数在函数中则临时地被函数参数所掩盖或隐藏 3)$0比较特

Shell 编程 函数

本篇主要写一些shell脚本函数的使用. 函数调用 #!/bin/bash sum(){ s=`expr 2 + 3` echo $s } sum [[email protected] ~]# vim sum.sh [[email protected] ~]# chmod +x sum.sh [[email protected] ~]# ./sum.sh 5 传递参数 #!/bin/bash sum(){ s=`expr $1 + $2` echo $s } sum 2 3 [[email pr

Shell编程基础篇

1.变量 用户自定义变量 用户可以按照下面的语法规则定义自己的变量:变量名=变量值 .要注意的一点是,在定义变量时,变量名前不应加符号"$",在引用变量的内容时则应在变量名前加"$":在给变量赋值时,等号两边一定不能留空格,若变量中本身就包含了空格,则整个字符串都要用双引号括起来. 位置变量 通过命令行给程序传递执行参数. $0:当前执行的进程/程序名 $n:(n为1-9的数字)第几个位置参数 预定义变量 $#:命令行中位置参数的个数 $*:所有位置参数的内容 $?

Shell编程基础篇-上

1.1 前言 1.1.1 为什么学Shell Shell脚本语言是实现Linux/UNIX系统管理及自动化运维所必备的重要工具, Linux/UNIX系统的底层及基础应用软件的核心大都涉及Shell脚本的内容.每一个合格 的Linux系统管理员或运维工程师,都需要能够熟练地编写Shell脚本语言,并能够阅 读系统及各类软件附带的Shell脚本内容.只有这样才能提升运维人员的工作效率,适 应曰益复杂的工作环境,减少不必要的重复工作,从而为个人的职场发展奠定较好的基础 1.1.2 什么是shell

Shell编程------函数应用

1. shell函数的返回值: 一般情况下,返回0表示运行成功,返回非0表示出现故障.对于返回值的查看,用$?命令. 2. shell函数的传入参数:       用脚本的位置参数作为传入参数,即:$1,[email protected] 3. shell语言的插入排序程序: #! /bin/bash function insertsort() { echo "please input a list: " read -a list for((i=1;i<${#list[@]};i

shell编程进阶篇

上一篇文章介绍的是shell的基础知识:https://blog.51cto.com/14048416/2355550??有人会说,shell简单啊,就是一些命令的堆砌啊,是的一些简单的操作仅仅执行几个命令就行了,但是相对一些复杂的业务和要求下,如果只能做到命令的堆砌,那也太有损shell的名声了.??小编通过一个例子给大家介绍,如果没有逻辑和条件,只是命令的堆砌,那么对维护Linux,是多么大的灾难. #需求:清除/var/log 下message 日志文件命令堆砌 #!/bin/bash #

2.shell编程-函数的高级用法

2.1.函数的定义和使用 函数基本使用 [[email protected]_0_9_centos ~]# test() > {} -bash: syntax error near unexpected token `{}' [root@VM_0_9_centos ~]# test() {} -bash: syntax error near unexpected token `{}' [root@VM_0_9_centos ~]# test() > { > echo "test

Shell编程应用篇之网站自动化备份

rsync是类unix系统下的数据镜像备份工具--remote sync.一款快速增量备份工具 Remote Sync,远程同步 支持本地复制,或者与其他SSH.rsync主机同步.与传统的cp.scp.tar备份方式相比,rsync具有安全性高.备份迅速.支持增量备份等优点,通过rsync可以解决对实时性要求不高的数据备份需求,例如定期的备份文件服务器数据到远端服务器,对本地磁盘定期做数据镜像等. 环境 centos 5.8(64)  192.168.23.130 (service) cent