目录
8、下载、安装、使用GUN shoot shell脚本函数库
完整笔记请前往此处获取:https://download.csdn.net/download/qq_55908180/88366003
1、基本的脚本函数
函数是一个脚本代码块,你可以为其命名并在代码中任何位置重用。要在脚本中使用该代码块时,只要使用所起的函数名就行了(这个过程称为调用函数)。
1.1、创建函数
在bash shell 脚本中有两种格式可以用来创建函数。
第一种格式使用关键字function,后跟分配给该代码块的函数名:
function name{
commands
}
name属性定义了赋予函数的唯一名称。脚本中定义的每个函数都必须有一个唯一的名称。commands是构成函数的一条或多条bash shell命令。在调用该函数时,bash shell会按命令在函数中出现的顺序依次执行、就像在普通脚本中一样。
第二种格式是更接近于其他语言的定义函数方式:
name() {
commands
}
1.2、使用函数
想在脚本中使用函数,只需要像其他shell命令一样,在行中指定函数名就行了。如:
#!/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"
注意:函数定义不一定非得是shell脚本中首先要做的事,如果在函数被定义前使用函数,就会收到错误消息。如:
#!/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"
func2
echo "Now this is the end of the script"
function func2 {
echo "This is an example of a function"
}
注意:函数名必须是唯一的,否则也会有问题。如果你重定义了函数,新定义会覆盖原来函数的定义,并且这一切不会产生任何错误消息。如:
#!/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"
2、返回值
bash shell会把函数当作一个小型脚本,运行结束时会返回一个退出状态码。有3种不同的方法来为函数生成退出状态码。
2.1、默认退出状态码
默认情况下,函数的退出状态码是函数中最后一条命令返回的退出状态码,在函数执行结束后,可以用标准变量$?为函数生成退出状态码。如:
#!/bin/bash
func1() {
echo "trying to display a non-existent file"
ls -l badfile
}
echo "testing the function: "
func1
echo "The exit status is: $?"
下面的例子可以知道函数中其他的命令是否成功运行,如:
#!/bin/bash
func1() {
ls -l badfile
echo "This was a test of a bad command"
}
echo "testing the function: "
func1
echo "The exit status is: $?"
注意:使用函数的默认退出状态码是很危险的。不过好在有几种办法可以解决这个问题。
2.2、使用return命令
return命令允许指定一个整数值来定义函数的退出状态码,从而提供了一种简单的途径来编程设定函数退出状态码。如:
#!/bin/bash
function db1 {
read -p "Enter a value: " value
echo "doubling the value"
return $[ $value * 2 ]
}
db1
echo "The new value is $?"
db1函数会将$value变量中用户输入的值翻倍.然后用return命令返回结果。脚本用s ?变量显示了该值。
但当用这种方法从函数中返回值时,要小心了。记住下面两条技巧来避免问题:
1、函数一结束就取返回值;
2、退出状态码必须是0~255。如果退出状态码大于256,都会随机生成一个错误值如:
2.3、使用函数输出
获得任何类型的函数输出,并将其保存到变量中。
result=’dbl’
这个命令会将dbl函数的输出赋给$result变量。如:
#!/bin/bash
function dbl {
read -p "Enter a value: " value
echo $[ $value * 2 ]
}
result=$(dbl)
echo "The new value is $result"
3、在函数中使用变量
在上面的例子中用来一个叫$value的变量来保存处理后的值。在函数中使用变量时,一定要注意它们的定义方式以及处理方式,这是常见错误的根源。
3.1、向函数传递参数
函数可以使用标准的参数环境变量来表示命令行上传给函数的参数,也可以用特殊变量s#来判断传给函数的参数数目。
在脚本中指定函数时,必须将参数和函数放在同一行,如: func1 $value 10
#!/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
注释:首先,addem函数会检查脚本传给它的参数数目。如果没有任何参数,或者参数多于两个,会返回值-1。如果只有一个参数,addem会将参数与自身相加。如果有两个参数,addem会将它们进行相加。
由于函数使用特殊参数环境变量作为自己的参数值,因此它无法直接获取脚本在命令行中的参数值。要在函数中使用这些值,必须在调用函数时手动将它们传过去。如:
#!/bin/bash
function func1 {
echo $[ $1*$2 ]
}
if [ $# -eq 2 ]
then
value=$(func1 $1 $2)
echo "This result is $value"
else
echo "Usage: badtest1 a b"
fi
3.2、在函数中处理变量
函数使用两种类型的变量:全局变量和局部变量
1、全局变量
在脚本的任何地方都有效的变量。默认情况下,在脚本中定义的任何变量都是全局变量。在函数外定义的变量可在函数内正常访问。如:
#!/bin/bash
function dbl {
value=$[ $value * 2 ]
}
read -p "Enter a value: " value
dbl
echo "The new value is: $value"
2、局部变量
只要在变量声明的前面加上local关键字就可以把函数内部使用的任何变量都声明成局部变量。local temp
也可以在变量赋值语句中使用local关键字:local temp=$[ $value + 5 ]
local关键字保证了变量只局限在该函数中。如果脚本中在该函数之外有同样名字的变量,那么shell将会保持这两个变量的值是分离的。现在你就能很轻松地将函数变量和脚本变量隔离开了,只共享需要共享的变量。如:
#!/bin/bash
function func1 {
local temp=$[ $value + 5 ]
result=$[ $temp * 2 ]
}
temp=3
value=9
func1
echo "The result is $result"
if [ $temp -gt $value ]
then
echo "temp is lager"
else
echo "temp is smaller"
fi
4、数组变量和函数
4.1、向函数传数组参数
把数组变量当做单个参数传递的话,会不起作用。如:
#!/bin/bash
function test {
echo "The parameters are: $@"
thisarray=$1
echo "The received array is: ${thisarray[*]}"
}
myarray=(1 2 3 4 5 )
echo "The original array is: ${myarray[*]}"
test $myarray
如果试图将该数组变量作为函数参数,函数只会取数组变量的第一个值。
要解决这个问题,就要把该数组变量的值分解成单个的值,然后将这些值作为函数参数使用。在函数内部,可以将所有的参数重新组合成一个新的变量。下面是个具体的例子。
#!/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"
4.2、从函数返回数组
从函数里向shell脚本传回数组变量也用类似的方法。函数用echo语句来按正确顺序输出单个数组值,然后脚本再将它们重新放进一个新的数组变量中。如:
#!/bin/bash
function array1 {
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=($(array1 $arg1))
echo "The new array is: ${result[*]}"
5、函数递归
首先说一下什么是函数递归:函数递归是指一个函数在执行的过程中调用了自己。它可以用于解决需要重复执行同一操作的问题,以及涉及到数学和计算机科学中的问题。递归函数必须包含一个基础案例,以避免无限递归。
局部函数变量的一个特性是自成体系。除了从脚本命令行处获得的变量,自成体系的函数不需要使用任何外部资源。
递归算法的经典例子是计算阶乘。下面例子给出一个简单的递归计算一个数的阶乘的例子。如:
#!/bin/bash
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"
6、创建库
为了避免同一段代码在多个脚本中都要重复使用,而每一次都要定义。创建函数库文件就显得很重要。如:下面创建了一个脚本中所需的函数的公用库文件。
如果尝试像普通脚本一样运行库文件,函数并不会出现在脚本中。如:
使用函数库的关键在于source命令。source命令会在当前shell上下文中执行命令,而不是创建一个新shell。可以用source命令来在shell脚本中运行库文件脚本。这样脚本就可以使用库中的函数了。
source命令有个快捷的别名,叫作点操作符( dot operator )。要在shell脚本中运行myfuncs库文件、只需添加下面这行: . ./myfuncs
如:
7、在命令行上使用函数
一旦在shell中定义了函数,就可以在整个系统中使用它了,无需担心脚本是不是在PATH环境变量里。重点在于让shell能够识别这些函数。有几种方法可以实现。
7.1、在命令行上创建函数
因为shell会解释用户输入的命令,所以可以在命令行上直接定义一个函数。有两种方法。一种方法是采用单行方式定义函数。如:
注意:当在命令行上定义函数时,你必须记得在每个命令后面加个分号,这样shell就能知道在哪里是命令的起止了。如:
另一种方法是采用多行方式来定义函数。在定义时,bash shell会使用次提示符来提示输入更多命令。用这种方法,你不用在每条命令的末尾放一个分号,只要按下回车键就行。如:
7.2、在.bashrc文件中定义函数
在命令行上直接定义shell函数的明显缺点是退出shell时,函数就没有了。对于复杂的函数来说,下一次还要重新定义。
有一个非常简单的方法是将函数定义在一个特定的位置,这个位置在每次启动一个新shell的时候,都会由shell重新载入。
7.2.1、直接定义函数
可以直接在主目录下的.bashrc文件中定义函数,但是注意,不要删除该文件里的东西,直接把要加的函数放在文件末尾就行了。如:
# .bashrc
if [ -r /etc/bashrc ]; then
. /etc/bashrc
fi
function addem{
echo $[ $1 + $2 ]
}
该函数会在下次启动新bash shell时生效。随后你就能在系统上任意地方使用这个函数了。
7.2.2、读取函数文件
只要是在shell脚本中,都可以用source命令(或者它的别名点操作符)将库文件中的函数添加到你的.bashrc脚本中。
# .bashrc
if [ -r /etc/bashrc ]; then
. /etc/bashrc
fi
. /home/txf/shell/myfuncs
注意红色框:库文件的路径名一定要正确,这样shell才能找到该文件。加好之后重启一下命令行,就可以直接调用了。
8、下载、安装、使用GUN shoot shell脚本函数库
shtool库提供了一些简单的shell脚本函数,可以用来完成日常的shell功能。
8.1、下载及安装
下载地址:https://mirrors.aliyun.com/gnu/shtool/
使用tar命令提取文件
tar -zxvf shtool-2.0.8.tar.gz
8.2构建库
shtool文件必须针对特定的Linux环境进行配置。配置工作必须使用标准的configure和make命令,这两个命令常用于C编程环境。要构建库文件,只要输入:
configure命令会检查构建shtool库文件所必需的软件。一旦发现了所需的工具,它会使用工具路径修改配置文件。
make命令负责构建shtool库文件。最终的结果( shtool )是一个完整的库软件包。你也可以使用make命令测试这个库文件。
使用make命令的install选项就可以将库安装到Linux系统中的公用位置,这样所有的脚本就都能够使用这个库了。
8.3shtool库函数
shtool库提供了大量方便的、可用于shell脚本的函数。
每个shtool函数都包含大量的选项和参数,你可以利用它们改变函数的工作方式。下面是shtool函数的使用格式:
shtool [ options] [ function [options] [args ] ]
8.4使用库
可以在命令行或自己的shell脚本中直接使用shtool函数。下面是一个在shell脚本中使用platform函数的例子。