shell 函数

在C语言中,我们可以给一个经常使用的代码块(使用一对大括号{}包起来的代码)添加一个名字,然后直接通过这个名字去复用(调用)这个代码块。这个名字和代码块也就是C语言的函数,这个名字就叫函数名,这个代码块就是函数体(函数的实现)。

shell脚本中,我们也可以将一组经常使用的命令与一个名称进行关联,后续可以直接通过这个名称来调用执行。这个名称也就成了shell中的函数,shell函数的定义格式如下所示:

[function] 函数名称() 复合命令块 [重定向]

其中[]里的保留字function和重定向是可选的,而符合命令块通常是使用一对大括号{}包起来的命令列表,因此函数的定义格式可以简化为:

函数名称(){
    命令1
    命令2
    if-else组合命令
    while-for循环命令
    [函数返回值]
}

调用这个函数时,如果需要传递传参,参数放在函数名后面即可,多个参数之间使用空格隔开。

#!/bin/bash

function my_print {
    echo "param num: $#"
    i=1
    for param in $@
    do 
        echo "param$i : $param"
        ((i++))
    done
    return $?
}

my_print hello zhaixue.cc

shell中的一些特殊变量$#表示传递的参数个数,$@表示传递进来的所有参数,$?表示最后一个命令的返回状态,可以作为函数的返回值,返回值是可选的。在脚本里定义好函数my_print,后面就可以直接在脚本里调用,参数放在调用函数名的后面,各个参数之间用空格隔开。

脚本的运行结果如下:

root@pc:/home/demo# ./hello.sh 
param num: 2
param1: hello
param2: zhaixue.cc

shell间接变量的两种引用方式

通过上面的学习,我们知道,在参数传递过程中,还有一些位置参数可以使用:无论是给脚本传参数,还是给函数传参数,$0表示运行的命令名称,$1表示第一个参数,$2表示第二个参数…,因此,我们可以把上面的函数使用位置参数来实现。

#!/bin/bash

function my_print {
    echo "param num: $#"
    for((i=1; i<=$#;i++))
    do 
        eval echo "param$i : ${!i}"
    done
    return $?
}

my_print hello zhaixue.cc

shell中,我们可以使用$i使用一个变量,但不支持类似于 $$i 或 ${$i} 这种间接使用变量的形式,因此,我们可以使用变量扩展${!i}的形式,shell在解析这个变量时看到这个感叹号,就知道是个i是个间接变量,会将i变量的值作为新的位置变量的名称,并继续扩展这个新的变量。

目前的shell解释器中,bash是支持这种间接变量的引用方式的,而为了保持与其他shell的兼容性,我们可以采用另外一种间接变量的引用方式:eval \$$a

#!/bin/bash

function my_print {
    echo "param num: $#"
    for((i=1; i<=$#;i++))
    do 
        eval echo "param$i : \$$i"
    done
    return $?
}

my_print hello zhaixue.cc

如脚本所示,跟上一个脚本的运行结果是一样的:

root@pc:/home/demo# ./hello.sh 
param num: 2
param1 : hello
param2 : zhaixue.cc

我们在shell函数my_print中仅仅是打印了传递过来的参数,并未对参数做任何处理。而实际的shell函数一般都是完成某个特定的功能,需要对传递的参数进行各种处理。

《Linux三剑客》视频教程:Linux下开发工具vim、Git、Makefile、autotools、qemu、debug精讲,从零开始一步一步写项目的Makefile,提供企业级Makefile模板,Git操作实战,vim从新手到高手,一步一步打造类似Source Insight的IDE!详情点击:王利涛老师个人淘宝店:Linux三剑客