shell读书笔记10

高级shell脚本编程
一、创建函数
1、基本的脚本函数
1.1、创建函数
有两种格式可以用来在bash shell脚本中创建函数。
I、第一种格式采用关键字function,后跟分配给该代码块的函数名

function name {
commands
}

II、第二种格式更接近于其他编程语言中定义函数的方式

name() {
commands
}

1.2、使用函数

$ cat test1
#!/bin/bash
# using a function in a script
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"
$
$ ./test1
This is an example of a function
This is an example of a function
This is an example of a function
This is an example of a function
This is an example of a function
This is the end of the loop
This is an example of a function
Now this is the end of the script
$

2、返回值
有3种不同的方法来为函数生成退出状态码
2.1、默认退出状态码
在函数执行结束后,可以用标准变量$?来确定函数的退出状态码

$ cat test4
#!/bin/bash
# testing the exit status of a function
func1() {
echo "trying to display a non-existent file"
ls -l badfile
}
echo "testing the function: "
func1
echo "The exit status is: $?"
$
$ ./test4
testing the function:
trying to display a non-existent file
ls: badfile: No such file or directory
The exit status is: 1
$

函数的退出状态码是1,这是因为函数中的最后一条命令没有成功运行。但你无法知道函数中其他命令中是否成功运行。看下面的例子。

$ cat test4b
#!/bin/bash
# testing the exit status of a function
func1() {
ls -l badfile
echo "This was a test of a bad command"
}
echo "testing the function:"
func1
echo "The exit status is: $?"
$
$ ./test4b
testing the function:
ls: badfile: No such file or directory
This was a test of a bad command
The exit status is: 0
$

这次,由于函数最后一条语句echo运行成功,该函数的退出状态码就是0,尽管其中有一条命令并没有正常运行。使用函数的默认退出状态码是很危险的。幸运的是,有几种办法可以解决这个问题。

2.2、使用return 命令
bash shell使用return命令来退出函数并返回特定的退出状态码。return命令允许指定一个整数值来定义函数的退出状态码,从而提供了一种简单的途径来编程设定函数退出状态码。

$ cat test5
#!/bin/bash
# using the return command in a function
function dbl {
read -p "Enter a value: " value
echo "doubling the value"
return $[ $value * 2 ]
}
dbl
echo "The new value is $?"
$

dbl函数会将 v a l u e 变 量 中 用 户 输 入 的 值 翻 倍 , 然 后 用 r e t u r n 命 令 返 回 结 果 。 脚 本 用 value变量中用户输入的值翻倍,然后用return命令返回结果。脚本用 valuereturn?变量显示了该值。
但当用这种方法从函数中返回值时,要小心了。记住下面两条技巧来避免问题:
 记住,函数一结束就取返回值;
 记住,退出状态码必须是0~255。
如果在用 ? 变 量 提 取 函 数 返 回 值 之 前 执 行 了 其 他 命 令 , 函 数 的 返 回 值 就 会 丢 失 。 记 住 , ?变量提取函数返回值之前执行了其他命令,函数的返回值就会丢失。记住, ??变量会返回执行的最后一条命令的退出状态码。
第二个问题界定了返回值的取值范围。由于退出状态码必须小于256,函数的结果必须生成一个小于256的整数值。任何大于256的值都会产生一个错误值。

$ ./test5
Enter a value: 200
doubling the value
The new value is 1
$

要返回较大的整数值或者字符串值的话,你就不能用这种返回值的方法了。

2.3、使用函数输出
正如可以将命令的输出保存到shell变量中一样,你也可以对函数的输出采用同样的处理办法。可以用这种技术来获得任何类型的函数输出,并将其保存到变量中:

result='dbl'

这个命令会将dbl函数的输出赋给$result变量。下面是在脚本中使用这种方法的例子。

$ cat test5b
#!/bin/bash
# using the echo to return a value
function dbl {
read -p "Enter a value: " value
echo $[ $value * 2 ]
}
result=$(dbl)
echo "The new value is $result"
$
$ ./test5b
Enter a value: 200
The new value is 400
$
$ ./test5b
Enter a value: 1000
The new value is 2000
$

3、在函数中使用变量
3.1、向函数传递参数
函数可以使用标准的参数环境变量来表示命令行上传给函数的参数。例如,函数名会在$0变量中定义,函数命令行上的任何参数都会通过$1、 2 等 定 义 。 也 可 以 用 特 殊 变 量 2等定义。也可以用特殊变量 2#来判断传给函数的参数数目。
在脚本中指定函数时,必须将参数和函数放在同一行,像这样:

func1 $value1 10

然后函数可以用参数环境变量来获得参数值。这里有个使用此方法向函数传值的例子。

$ cat test6
#!/bin/bash
# passing parameters to a function
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 20)
echo $value
$
$ ./test6
Adding 10 and 15: 25
Let's try adding just one number: 20
Now trying adding no numbers: -1
Finally, try adding three numbers: -1
$

3.2、在函数中处理变量
给shell脚本程序员带来麻烦的原因之一就是变量的作用域。作用域是变量可见的区域。函数中定义的变量与普通变量的作用域不同。也就是说,对脚本的其他部分而言,它们是隐藏的。
函数使用两种类型的变量:
 全局变量
 局部变量
下面几节将会介绍这两种类型的变量在函数中的用法。
I、全局变量
全局变量是在shell脚本中任何地方都有效的变量。如果你在脚本的主体部分定义了一个全局变量,那么可以在函数内读取它的值。类似地,如果你在函数内定义了一个全局变量,可以在脚本的主体部分读取它的值。
默认情况下,你在脚本中定义的任何变量都是全局变量。在函数外定义的变量可在函数内正常访问。

$ cat test8
#!/bin/bash
# using a global variable to pass a value
function dbl {
value=$[ $value * 2 ]
}
read -p "Enter a value: " value
dbl
echo "The new value is: $value"
$
$ ./test8
Enter a value: 450
The new value is: 900
$

II、局部变量
无需在函数中使用全局变量,函数内部使用的任何变量都可以被声明成局部变量。要实现这一点,只要在变量声明的前面加上local关键字就可以了。

local temp

local关键字保证了变量只局限在该函数中。如果脚本中在该函数之外有同样名字的变量,那么shell将会保持这两个变量的值是分离的。现在你就能很轻松地将函数变量和脚本变量隔离开了,只共享需要共享的变量。

$ cat test9
#!/bin/bash
# demonstrating the local keyword
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
$
$ ./test9
The result is 22
temp is smaller
$

现在,在func1函数中使用 t e m p 变 量 时 , 并 不 会 影 响 在 脚 本 主 体 中 赋 给 temp变量时,并不会影响在脚本主体中赋给 temptemp变量的值。

4、数组变量和函数
4.1、向函数传数组参数
向脚本函数传递数组变量的方法会有点不好理解。将数组变量当作单个参数传递的话,它不会起作用。

$ cat badtest3
#!/bin/bash
# trying to pass an array variable
function testit {
echo "The parameters are: $@"
thisarray=$1
echo "The received array is ${thisarray[*]}"
}
myarray=(1 2 3 4 5)
echo "The original array is: ${myarray[*]}"
testit $myarray
$
$ ./badtest3
The original array is: 1 2 3 4 5
The parameters are: 1
The received array is 1
$

如果你试图将该数组变量作为函数参数,函数只会取数组变量的第一个值。
要解决这个问题,你必须将该数组变量的值分解成单个的值,然后将这些值作为函数参数使用。在函数内部,可以将所有的参数重新组合成一个新的变量。下面是个具体的例子。

$ cat test10
#!/bin/bash
# array variable to function test
function testit {
local newarray
newarray=(;'echo "$@"')
echo "The new array value is: ${newarray[*]}"
}
myarray=(1 2 3 4 5)
echo "The original array is ${myarray[*]}"
testit ${myarray[*]}
$
$ ./test10
The original array is 1 2 3 4 5
The new array value is: 1 2 3 4 5
$

该脚本用$myarray变量来保存所有的数组元素,然后将它们都放在函数的命令行上。该函数随后从命令行参数中重建数组变量。在函数内部,数组仍然可以像其他数组一样使用。

$ cat test11
#!/bin/bash
# adding values in an array
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"
$
$ ./test11
The original array is: 1 2 3 4 5
The result is 15
$

4.2、从函数返回数组
从函数里向shell脚本传回数组变量也用类似的方法。函数用echo语句来按正确顺序输出单个数组值,然后脚本再将它们重新放进一个新的数组变量中。

$ cat test12
#!/bin/bash
# returning an array value
function arraydblr {
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=($(arraydblr $arg1))
echo "The new array is: ${result[*]}"
$
$ ./test12
The original array is: 1 2 3 4 5
The new array is: 2 4 6 8 10
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值