Linux Shell 函数、数组模板

01. 基本的函数脚本

01. 创建函数

函数是一个脚本代码块,你可以为其命名并在代码中任何位置重用。要在脚本中使用该代码块时,只要使用所起的函数名就行了(这个过程称为调用函数)。

name属性定义了赋予函数的唯一名称。脚本中定义的每个函数都必须有一个唯一的名称。下边是两种创建函数的方式。

function name {
commands
}
name() {
commands
}
02. 使用函数

必须先定义函数,再调用函数

#!/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"

如果你重定义了函数,新定义会覆盖原来函数的定义,这一切不会产生任何错误消息。

函数定义不一定非得是shell脚本中首先要做的事(但必须先定义后调用,也可以定义到函数库中,方便脚本调用)。

02. 返回值

01. 默认退出状态码

默认情况下,函数的退出状态码是函数中最后一条命令返回的退出状态码。在函数执行结束后,可以用标准变量 $? 来确定函数的退出状态码。

#!/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: $?"

缺陷:无法判断整个函数中的命令是否都执行成功了,使用函数的默认退出状态码是很危险的。

02. 使用return 命令

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

#!/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 $?"

特别需要注意两点,否则会报错:

  • 记住,函数一结束就取返回值
  • 记住,退出状态码必须是0~255
03. 使用函数输出

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

#!/bin/bash
# using the echo to return a value
function dbl {
	read -p "Enter a value: " value
	# 函数输出,使用echo
	echo $[ $value * 2 ]
}

# 这个命令会将dbl函数的输出赋给$result变量。
result=$(dbl)
echo "The new value is $result"

说明:通过这种技术,你还可以返回浮点值和字符串值。这使它成为一种获取函数返回值的强大方法。

03. 在函数中使用变量

01. 向函数传递参数

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

函数可以用参数环境变量来获得参数值

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

value=$(addem 10 15 20)
echo $value

由于函数使用特殊参数环境变量作为自己的参数值,因此它无法直接获取脚本在命令行中的参数值(函数参数与脚本参数使用了相同的特殊变量,这种情况不能并存)。

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

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
02. 在函数中处理变量

函数中定义的变量与普通变量的作用域不同。也就是说,对脚本的其他部分而言,它们是隐藏的

全局变量

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

默认情况下,你在脚本中定义的任何变量都是全局变量。在函数外定义的变量可在函数内正常访问。

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

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

$value变量在函数外定义并被赋值。当dbl函数被调用时,该变量及其值在函数中都依然有效。如果变量在函数内被赋予了新值,那么在脚本中引用该变量时,新值也依然有效。

局部变量

如果你想在不同的shell脚本中使用函数的话。它要求你清清楚楚地知道函数中具体使用了哪些变量,包括那些用来计算非返回值的变量。

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

local temp
local temp=$[ $value + 5 ]

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

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

04. 数组变量和函数

01. 向函数传数组参数

将数组变量当作单个参数传递的话,它不会起作用。

#!/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

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

#!/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[*]}

传入函数内部后,数组仍然可以正常使用。

!/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"
02. 从函数返回数组

函数用echo语句来按正确顺序输出单个数组值,然后脚本再将它们重新放进一个新的数组变量中。

#!/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[*]}"

05. 递归函数

递归算法的经典例子是计算阶乘。一个数的阶乘是该数之前的所有数乘以该数的值。因此,要计算5的阶乘,可以执行如下方程:

5! = 1 * 2 * 3 * 4 * 5 = 120

使用递归,方程可以简化成以下形式:

x! = x * (x-1)!

也就是说, x的阶乘等于x乘以x-1的阶乘。这可以用简单的递归脚本表达为:

# 每递归一次,x!的乘积形式展开一次,直到全部展开为乘积形式
function factorial {
if [ $1 -eq 1 ]
then
	echo 1
else
	local temp=$[ $1 - 1 ]
	# 调用自己本身
	local result='factorial $temp'
	echo $[ $result * $1 ]
fi
}

read -p "Enter value: " value
result=$(factorial $value)
echo "The factorial of $value is: $result"

06. 创建函数库

如果你碰巧要在多个脚本中使用同一段代码呢?bash shell允许创建函数库文件,然后在多个脚本中引用该库文件。

#!/bin/bash
# using functions defined in a library file
# 加载函数库文件,当前目录下的 ./myfuncs
. ./myfuncs

#
......
#

使用函数库的关键在于source命令。 source命令会在当前shell上下文中执行命令,而不是创建一个新shell。可以用source命令来在shell脚本中运行库文件脚本。这样脚本就可以使用库中的函数了。source命令还有个快捷的别名,称作点操作符。

07. 在命令行上使用函数

01. 在命令行上创建函数

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

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

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

$ function multem {
> echo $[ $1 * $2 ]
> }
02. 在.bashrc 文件中定义函数

在命令行上直接定义shell函数的明显缺点是退出shell时,函数就消失了。一个非常简单的方法是将函数定义在一个特定的位置,这个位置在每次启动一个新shell的时候,都会由shell重新载入。最佳地点就是 .bashrc 文件。

  • 直接在文件中定义函数
  • 也可以直接加载函数库文件
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值