侧边栏壁纸
博主头像
张种恩的技术小栈博主等级

行动起来,活在当下

  • 累计撰写 747 篇文章
  • 累计创建 65 个标签
  • 累计收到 39 条评论

目 录CONTENT

文章目录

Shell脚本编程(14)之在函数中使用变量

zze
zze
2019-12-24 / 0 评论 / 0 点赞 / 573 阅读 / 4032 字

不定期更新相关视频,抖音点击左上角加号后扫一扫右方侧边栏二维码关注我~正在更新《Shell其实很简单》系列

本部分内容参考自《Linux命令行与shell脚本编程大全 第3版》。

向函数传递参数

bash shell 会将函数当作小型脚本来对待。这意味着你可以像普通脚本那样向函数传递参数。
函数可以使用标准的参数环境变量来表示命令行上传给函数的参数。例如,函数名会在 $0 变量中定义,函数命令行上的任何参数都会通过 $1$2 等定义。也可以用特殊变量 $# 来判断传给函数的参数数目。
在脚本中指定函数时,必须将参数和函数放在同一行,像这样:

func1 $value1 10

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

$ cat test5.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 20)
echo $value
$ ./test5.sh 
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

脚本中的 addem 函数首先会检查脚本传给它的参数数目。如果没有任何参数,或者参数多于两个, addem 会返回值 -1。如果只有一个参数, addem 会将参数与自身相加。如果有两个参数, addem 会将它们进行相加。
由于函数使用特殊参数环境变量作为自己的参数值,因此它无法直接获取脚本在命令行中的参数值。下面的例子将会运行失败。

$ cat test6.sh 
#!/bin/bash
function badfunc1 {
	echo $[ $1 * $2 ]
}
if [ $# -eq 2 ]
then
	value=$(badfunc1)
	echo "The result is $value"
else
	echo "Usage: badtest1 a b"
fi
$ ./test6.sh
Usage: badtest1 a b
$ ./test6.sh 1 2
./test6.sh: line 10: *  : syntax error: operand expected (error token is "*  ")
The result is 

尽管函数也使用了 $1$2 变量,但它们和脚本主体中的 $1$2 变量并不相同。要在函数中使用这些值,必须在调用函数时手动将它们传过去。

$ cat ./test6a.sh
#!/bin/bash
function func7 {
	echo $[ $1 * $2 ]
}
if [ $# -eq 2 ]
then
	value=$(func7 $1 $2)
	echo "The result is $value"
else
	echo "Usage: badtest1 a b"
fi
$ ./test6a.sh 
Usage: badtest1 a b
$ ./test6a.sh 2 3
The result is 6

通过将 $1$2 变量传给函数,它们就能跟其他变量一样供函数使用了。

在函数中处理变量

给 shell 脚本程序员带来麻烦的原因之一就是变量的作用域。作用域是变量可见的区域。函数中定义的变量与普通变量的作用域不同。也就是说,对脚本的其他部分而言,它们是隐藏的。
函数使用两种类型的变量:

  • 全局变量;
  • 局部变量;

下面将会介绍这两种类型的变量在函数中的用法。

全局变量

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

$ cat test7.sh 
#!/bin/bash
function dbl {
	value=$[ $value * 2 ]
}
read -p "Enter a value: " value
dbl
echo "The new value is: $value"
$ ./test7.sh 
Enter a value: 2
The new value is: 4

$value 变量在函数外定义并被赋值。当 dbl 函数被调用时,该变量及其值在函数中都依然有效。如果变量在函数内被赋予了新值,那么在脚本中引用该变量时,新值也依然有效。
但这其实很危险,尤其是如果你想在不同的 shell 脚本中使用函数的话。它要求你清清楚楚地知道函数中具体使用了哪些变量,包括那些用来计算非返回值的变量。

局部变量

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

local temp

也可以在变量赋值语句中使用 local 关键字:

local temp=$[ $value + 5 ]

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

$ cat test8.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
$ ./test8.sh 
The result is 22
temp is smaller

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

0

评论区