第二十九课 LinuxShell编程七之创建函数

说明:本文部分内容均摘取自书籍《Linux命令行与shell脚本编程大全》,版权归原作者所有。《Linux命令行与shell脚本编程大全》(第三版)第十七章学习总结

第十七章:创建函数

本章内容

基本的脚本函数
返回值
在函数中使用变量
属组变量和函数
函数递归
创建库
在命令行上使用函数

17.1 基本的脚本函数

17.1.1 创建函数

格式一

function name{
    commands
}

格式二

name(){
    commands
}

说明

name属性定义了赋予函数的唯一名称
commands是构成函数的一条或多条bash shell命令

17.1.2 使用函数

编写test1.sh脚本

#!/bin/bash

function func1 {
    echo "This is an example of a function"
}

count=1
while [ $count -le 5 ]
do
    func1
    count=$[ $count + 1 ]
done

echo "This is the end of the loop"
func1
echo "Now this is the end of the script"

函数需先定义,再使用

编写test2.sh脚本

#!/bin/bash

count=1
echo "This line comes before the function definition"

function func1 {
    echo "This is an example of a function"
}

while [ $count -le 5 ]
do
    func1
    count=$[ $count + 1 ]
done
echo "This is the end of the loop"
func2
echo "Now this is the end of the script"

function func2 {
    echo "This is an example of a function"
}

函数名必须唯一,否则新定义的函数会覆盖原来函数

编写test3.sh脚本

#!/bin/bash

function func1 {
    echo "This is the first definition of the function name"
}

func1

function func1 {
    echo "This is a repeat of the same function name"
}

func1
echo "This is the end of the script"

17.2 返回值

bash shell会把函数当做一个小型脚本,运行结束时会返回一个退出状态码

17.2.1 默认退出状态码

默认情况下,函数的退出状态码时函数中最后一条命令返回的退出状态码
在函数执行后,可以用标准变量$?来确定函数的退出状态码
只能判断函数中最后一条命令是否运行成功,无法判断函数中其它命令
使用函数的默认退出状态码时很危险的

编写test4.sh脚本

#!/bin/bash

func1() {
     ls -l badfile
     echo "trying to display a non-existent file"
}

echo "testing the function:"
func1
echo "The exit status is: $?"

17.2.2 使用return命令

使用return命令来退出函数并返回指定一个整数值的退出状态码
函数一结束就去返回值
退出状态码必须时0~255

编写test5.sh脚本

#!/bin/bash

function db1 {
    read -p "Enter a value: " value
    echo "doubling the value"
    return $[ $value * 2 ]
}

db1
echo "The new value is $?"

17.2.3 使用函数输出

可以将函数的输出保存到变量中

编写test5b.sh脚本

#!/bin/bash

function db1 {
    read -p "Enter a value: " value
    echo $[ $value *2 ]
}

result=$(db1)
echo "The new value is $result"

17.3 在函数中使用变量

17.3.1 向函数传递参数

函数可以使用标准的参数环境变量来表示命令行上传给函数的参数。
例如,函数名会在$0变量中定义,函数命令行上的任何参数都会通过$1、$2等定义。
也可以用特殊变量$#来判断传给函数的参数数目。

在脚本中指定函数时,必须将参数和函数放在同一行

编写test6.sh脚本

#!/bin/bash

function addem {
    if [ $# -eq 0 ] || [ $# -gt 2 ]
    then
        echo -1
    elif [ $# -eq 1 ]
    then
        echo $[ $1 + $1 ]
    else
        echo $[ $1 + $2 ]
    fi
}

echo -n "Adding 10 and 15:"
value=$(addem 10 15)
echo $value
echo -n "Let's try adding just one number:"
value=$(addem 10)
echo $value
echo -n "Now trying adding no numbers:"
value=$(addem)
echo $value
echo -n "Finally, try adding three numbers:"
value=$(addem 10 15 200)
echo $value

将传递给脚本的变量传给函数

编写test7.sh脚本

#!/bin/bash

function func7 {
    echo $[ $1 * $2 ]
}

if [ $# -eq 2 ]
then
    value=$(func7 $1 $2)
    echo "The result is $value"
else
    echo "Usage: test7 a b"
fi

17.3.2 在函数中处理变量

1.全局变量

全局变量是在shell脚本中任何地方都有效的变量。
如果你在脚本的主体部分定义了一个全局变量,那么可以在函数内读取它的值。
如果你在函数内定义了一个全局变量,可以在脚本的主题部分读取它的值。
默认情况下,在脚本中定义的任何变量都是全局变量,在函数外定义的变量可以在函数内访问。

编写test8.sh脚本

#!/bin/bash

function db1 {
    value=$[ $value * 2 ]
}

read -p "Enter a value: " value
db1
echo "The new value is: $value"

2.局部变量

无需在函数中使用全局变量,函数内部使用的任何变量都可以被声明成局部变量。
在变量声明的前面加上local关键字即可。
也可以在变量赋值语句中使用local关键字。

编写test9.sh脚本

#!/bin/bash

function func1 {
    local temp=$[ $value + 5 ]
    result=$[ $temp * 2 ]
}

temp=4
value=6

func1
echo "The result is $result"
if [ $temp -gt $value ]
then
    echo "temp is larger"
else
    echo "temp is smaller"
fi

17.4 数组变量和函数

17.4.1 向函数传数组参数

将数组的值分解成单个的值作为函数参数使用

编写test10.sh脚本

#!/bin/bash

function testit {
    local newarray
    newarray=($@)
    echo "The new array value is: ${newarray[*]}"
}

myarray=(1 2 3 4 5)
echo "The original array is ${myarray[*]}"
testit ${myarray[*]}

编写test11.sh脚本

#!/bin/bash

function addarray {
    local sum=0
    local newarray
    newarray=($(echo "$@"))
    for value in ${newarray[*]}
    do
        sum=$[ $sum + $value ]
    done
    echo $sum
}

myarray=(1 2 3 4 5)
echo "The original array is: ${myarray[*]}"
arg1=$(echo ${myarray[*]})
result=$(addarray $arg1)
echo "The result is $result"

17.4.2 从函数返回数组

从函数里向shell脚本传回数组变量

编写test12.sh脚本

#!/bin/bash

function arraydb1r {
    local origarray
    local newarray
    local elements
    local i
    origarray=($(echo "$@"))
    newarray=($(echo "$@"))
    elements=$[ $# -1 ]
    for (( i = 0; i<= $elements; i++ ))
    {
        newarray[$i]=$[ ${origarray[$i]} * 2 ]
    }
    echo ${newarray[*]}
}

myarray=(1 2 3 4 5)
echo "The original array is: ${myarray[*]}"
arg1=$(echo ${myarray[*]})
result=($(arraydb1r $arg1))
echo "The new array is: ${result[*]}"

创建库

如果多个脚本需要使用同一段代码,可以使用函数库文件,然后在多个脚本中引用该库文件

1.创建一个库文件

编写myfuncs文件

function addem {
    echo $[ $1 + $2 ]
}

function multem {
    echo $[ $1 * $2 ]
}

function divem {
    if [ $2 -ne 0 ]
    then
        echo $[ $1 / $2 ]
    else
        echo -1
    fi
}

使用这个库文件的错误方式

$ cat badtest4
#!/bin/bash
# using a library file the wrong way
./myfuncs
result=$(addem 10 15)
echo "The result is $result"
$
$ ./badtest4
./badtest4: addem: command not found
The result is
$

问题出在shell函数的作用域上。shell函数仅在定义它的shell会话内有效。
如果你在shell下运行badtest4脚本,shell会创建一个新的shell并在其中
加载myfuncs脚本。myfuncs会为那个新shell定义这三个函数,但当你在badtest4要用到这些函数的脚本时,它们是无法使用的。

2.使用这个库文件的正确方式

编写test14.sh脚本

#!/bin/bash
. ./myfuncs

value1=10
value2=5
result1=$(addem $value1 $value2)
result2=$(multem $value1 $value2)
result3=$(divem $value1 $value2)
echo "The result of adding them is: $result1"
echo "The result of multiplying them is: $result2"
echo "The result of dividing them is: $result3"

使用函数库的关键在于 source 命令。 source 命令会在当前shell上下文中执行命令,而不是创建一个新shell。可以用 source 命令来在shell脚本中运行库文件脚本。这样脚本就可以使用库中的函数了。
source 命令有个快捷的别名,称作点操作符(dot operator)。要在shell脚本中运行myfuncs库文件,只需添加下面这行:
. ./myfuncs
这个例子假定myfuncs库文件和shell脚本位于同一目录。如果不是,你需要使用相应路径访问该文件。

在命令行上使用函数

17.7.1 在命令行上创建函数

因为shell会解释用户输入的命令,所以可以在命令行上直接定义一个函数。有两种方法。
一种方法是采用单行方式定义函数。

$ function divem { echo $[ $1 / $2 ]; }
$ divem 100 5
20

当在命令行上定义函数时,你必须记得在每个命令后面加个分号,这样shell就能知道在哪里
是命令的起止了。

$ function doubleit { read -p "Enter value: " value; echo $[$value * 2 ]; }
$ doubleit
Enter value: 20
40

另一种方法是采用多行方式来定义函数。在定义时,bash shell会使用次提示符来提示输入更
多命令。用这种方法,你不用在每条命令的末尾放一个分号,只要按下回车键就行。

$ function multem {
> echo $[ $1 * $2 ]
> }
$ multem 2 5
10

在函数的尾部使用花括号,shell就会知道你已经完成了函数的定义。

在命令行上创建函数时要特别小心。如果你给函数起了个跟内建命令或另一个命令相同
的名字,函数将会覆盖原来的命令,如果你这样做了,请使用unset -f xxxfun命令删除函数定义

在.bashrc文件中定义函数


1.直接定义函数

可以直接在主目录下的.bashrc文件中定义函数

如在文件末尾加上

function addem {
    echo $[ $1 + $2 ]
}

2.读取函数文件

可以使用source命令(即点操作符)将库文件中的函数添加到.bashrc脚本中

如在文件末尾加上

. /root/myfuncs

库中的所有函数都可在命令行界面下使用了。

$ addem 10 5
15
$ multem 10 5
50
$ divem 10 5
2

小结

shell脚本函数允许将脚本中多处用到的代码放到一个地方。可以创建一个包含该代码块的函数,然后在脚本中通过函数名来引用这块代码,而不用一次次重复写那段代码。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,009评论 5 474
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,808评论 2 378
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 148,891评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,283评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,285评论 5 363
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,409评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,809评论 3 393
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,487评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,680评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,499评论 2 318
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,548评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,268评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,815评论 3 304
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,872评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,102评论 1 258
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,683评论 2 348
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,253评论 2 341

推荐阅读更多精彩内容