网站备案审核通过时间,温岭市住房和城乡建设局网站,网站图标在哪里修改,网站优化任务Linux命令行与Shell脚本编程
第一章 文章目录 Linux命令行与Shell脚本编程六.函数6.1.脚本函数基础6.1.1.创建函数6.1.2.使用函数 6.2.函数返回值6.2.1.默认的退出状态码6.2.2.使用return命令6.2.3.使用函数输出 6.3.函数中使用变量6.3.1.向函数传递参数6.3.2.在函数中处理变量…Linux命令行与Shell脚本编程
第一章 文章目录 Linux命令行与Shell脚本编程六.函数6.1.脚本函数基础6.1.1.创建函数6.1.2.使用函数 6.2.函数返回值6.2.1.默认的退出状态码6.2.2.使用return命令6.2.3.使用函数输出 6.3.函数中使用变量6.3.1.向函数传递参数6.3.2.在函数中处理变量全局变量局部变量 6.4.数组变量和函数6.4.1.向函数中传递数组6.4.2.从函数返回数组 6.5.函数递归6.6.创建库6.7.在命令行中使用函数6.7.1.命令行中创建函数 6.7.2.在.bashrc文件中定义函数6.8.共享库函数6.8.1.下载安装 六.函数
脚本函数基础函数返回值在函数中使用变量数组变量和函数函数递归创建库在命令行中使用函数
可以将shell脚本代码放入函数中封装起来这样就能在脚本的任意位置多次使用.
6.1.脚本函数基础
函数是一个脚本代码块可以并在脚本中的任何位置重用它。当需要在脚本中使用该代码块时直接通过函数名调用.
6.1.1.创建函数
bash shell脚本中创建函数的语法有两种。
使用关键字function
function name {//函数的唯一名称。脚本中的函数名不能重复commands //组成函数的一个或多个bash shell命令。
}近其他编程语言中定义函数的方式
name() {//函数名后的空括号表明正在定义的是一个函数
commands
}6.1.2.使用函数
使用函数名调用函数
$ cat test1
#!/bin/bash
# using a function in a script
function func {echo This is an example of a function
}
count1
while [ $count -le 5 ]
dofunccount$[ $count 1 ]
done
$ ./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函数定义不一定非要放在shell脚本的最开始部分,但必须定义在调用之后,在函数被定义之前调用则会收到一条错误消息.
func: command not found如果定义了同名函数新定义就会覆盖函数原先的定义而不会有任何错误消息.
6.2.函数返回值
bash shell把函数视为一个小型脚本运行结束时会返回一个退出状态码.
有3种方法能为函数生成退出状态码。
6.2.1.默认的退出状态码
函数的退出状态码是函数中最后一个命令返回的退出状态码。函数执行结束后可以使用标准变量 $? 来确定函数的退出状态码.
函数执行一结束就立刻读取返回值。用$?变量提取函数返回值之前执行了其他命令函数的返回值会丢失。
#!/bin/bash
func1() {## 命令执行失败ls -l badfile
}
echo testing the function:
func1
echo The exit status is: $?
testing the function:
trying to display a non-existent file
ls: badfile: No such file or directory
The exit status is: 1退出状态码是1因为函数中的最后一个命令执行失败.使用函数的默认退出状态码是一种危险的做法. ps: 函数最执行成功退出状态码为0.
6.2.2.使用return命令
bash shell会使用return命令以特定的退出状态码退出函数。return命令允许指定一个整数值作为函数的退出状态码.
$ cat test5
#!/bin/bash
# using the return command in a functionfunction dbl {read -p Enter a value: valueecho doubling the valuereturn $[ $value * 2 ]
}dbl
echo The new value is $?
$
$ ./test5
Enter a value: 200
doubling the value
The new value is 1
$大于255的任何数值都会产生错误的值.
6.2.3.使用函数输出
需要返回较大的整数值或字符串可以将函数的’输出’保存到shell变量中.
result$(function_name)$ cat test5b
#!/bin/bash
# using the echo to return a value
function dbl {read -p Enter a value: valueecho $[ $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
$函数会用echo语句来显示计算结果。脚本会获取dbl函数的输出而不是查看退出状态码。 dbl函数实际上输出了两条消息。read命令输出了一条简短的消息来向用户询问输入值。 bash shell并不将其作为STDOUT输出的一部分而是直接忽略。 如果用echo语句生成这条消息(Enter a value: )来询问用户消息就会与输出值一起被读入shell变量。 借助返回值方法,还可以返回浮点值和字符串.
6.3.函数中使用变量
在函数中使用变量时需要注意变量的定义方式和处理方式。
6.3.1.向函数传递参数
bash shell会将函数当作脚本来对待。可以像普通脚本那样向函数传递参数. 函数名保存在$0变量中函数参数依次保存在$1、 2 等变量中 . 可以用特殊变量 2等变量中.可以用特殊变量 2等变量中.可以用特殊变量#来确定传给函数的参数数量. (处理用户输入章节)
脚本中调用函数时必须将参数和函数名放在同一行.然后用位置变量来获取参数值。
func_name $value1 10示例:
$ cat test6
#!/bin/bash
function addem {if [ $# -eq 0 ] || [ $# -gt 2 ]thenecho -1elif [ $# -eq 1 ]thenecho $[ $1 $1 ]elseecho $[ $1 $2 ]fi
}echo -n Adding 10 and 15:
value$(addem 10 15)
echo $value
echo -n Lets try adding just one number:
value$(addem 10)
echo $value
echo -n Now try 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
Lets try adding just one number: 20
Now try adding no numbers: -1
Finally, try adding three numbers: -1函数使用位置变量访问函数参数无法直接获取脚本的命令行参数。
$ cat badtest1
#!/bin/bash
# trying to access script parameters inside a functionfunction badfunc1 {echo $[ $1 * $2 ]
}if [ $# -eq 2 ]
thenvalue$(badfunc1)echo The result is $value
elseecho Usage: badtest1 a b
fi
$
$ ./badtest1
Usage: badtest1 a b
$ ./badtest1 10 15
./badtest1: * : syntax error: operand expected (error token is *)
The result is
$尽管函数使用了$1变量和$2变量但和脚本主体中的$1变量和$2变量不同。 要在函数中使用脚本的命令行参数必须在调用函数时手动将其传入.
value$(badfunc1 $1 $2)在将$1和$2传给函数后就能跟其他变量一样供函数使用。
6.3.2.在函数中处理变量
变量的作用域是比较麻烦的.作用域是变量的有效区域. 函数有两种类型的变量:
全局变量局部变量
全局变量
在shell脚本内任何地方都有效的变量。 在默认情况下在脚本中定义的任何变量都是全局变量。在函数外定义的变量可在函数内正常访问.
$ cat test8
#!/bin/bash
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$value变量在函数外定义并被赋值。如果变量在函数内被赋予了新值那么在脚本中引用该变量时新值仍可用。
局部变量
在任何在函数内部使用的变量都可以被声明为局部变量.local关键字保证了变量仅在该函数中有效。
在变量声明之前加上local关键字.在变量赋值语句中使用local关键字.
local temp
local temp$[ $value 5 ]如果函数之外有同名变量两个变量的值互不干扰。
function func1 {local temp$[ $value 5 ]result$[ $temp * 2 ]
}6.4.数组变量和函数
在函数中使用数组变量.
6.4.1.向函数中传递数组
将数组变量当作单个参数传递不起作用. 数组变量作为函数参数进行传递则函数只会提取数组变量的第一个元素。
$ cat badtest3
#!/bin/bash
function testit {echo The parameters are: $thisarray$1echo 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 test11
#!/bin/bash
function addarray {local sum0local newarraynewarray(echo $)for value in ${newarray[*]}dosum$[ $sum $value ]doneecho $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 156.4.2.从函数返回数组
函数向shell脚本返回数组变量先用echo语句按正确顺序输出数组的各个元素脚本再将数组元素重组成一个新的数组变量.
$ cat test12
#!/bin/bash
function arraydblr {local origarraylocal newarraylocal elementslocal iorigarray($(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通过$arg1变量将数组元素作为参数传给arraydblr函数。 arraydblr函数将传入的参数重组成新的数组变量生成数组变量的副本。对数据元素进行操作并将结果存入函数中的数组变量副本。
6.5.函数递归
函数可以递归地调用. 递归函数通常有一个最终可以迭代到的基准值。 递归算法的经典例子是计算阶乘:
$ cat test13
#!/bin/bash
function factorial {if [ $1 -eq 1 ]thenecho 1elselocal 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
$
$ ./test13
Enter value: 5
The factorial of 5 is: 1206.6.创建库
使用函数可以为脚本省去一些重复性的输入工作.如果要在多个脚本中使用同一段代码,通过库解决. bash shell允许创建函数库文件然后在多个脚本中引用此库文件。
创建一个包含脚本中所需函数的公用库文件。$ cat myfuncs
function addem {echo $[ $1 $2 ]
}
function multem {echo $[ $1 * $2 ]
}在需要用到这些函数的脚本文件中包含myfuncs库文件. shell函数的作用域和环境变量一样shell函数仅在定义它的shell会话内有效。 如果在shell命令行界面运行myfuncs脚本那么shell会创建一个新的shell并在其中运行这个脚本。 这种情况下函数会定义在新shell中当运行另一个要用到这些函数的脚本时它们是无法使用的。 如果尝试像普通脚本文件那样运行库文件,函数也不会出现在脚本中.$ 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使用函数库的关键在于source命令。 source命令不会创建新的shell,而是在当前shell的上下文中执行命令. source命令称作点号操作符。在shell脚本中运行myfuncs库文件只需添加. ./myfuncs假定myfuncs库文件和shell脚本位于同一目录。否则需要使用正确路径访问该文件。$ cat test14
#!/bin/bash
. ./myfuncs
value110
value25
result1$(addem $value1 $value2)
echo The result of adding them is: $result1
$
$ ./test14
The result of adding them is: 156.7.在命令行中使用函数
有时候在命令行界面用函数执行一些十分复杂的操作.
6.7.1.命令行中创建函数
shell会解释用户输入的命令可以在命令行中直接定义一个函数. 在命令行创建函数时要特别小心。如果给函数起了一个跟内建命令或另一个命令相同的名字那么函数就会覆盖原来的命令。
单行方式 在命令行中定义函数时必须在每个命令后面加个分号,用于界定命令的起止.$ function divem { echo $[ $1 / $2 ]; }
$ divem 100 5
20多行方式 定义时bash shell会使用次提示符’来提示输入更多命令。使用这种方法无须在每条命令的末尾放置分号只需按下回车键. 输入函数尾部的花括号后完成函数的定义.$ function multem {echo $[ $1 * $2 ]}
$ multem 2 5
10在命令行中直接定义shell函数的一个明显缺点是在退出shell时函数也会消失。 在命令行创建函数时要特别小心。如果给函数起了一个跟内建命令或另一个命令相同的名字函数就会覆盖原来的命令。
6.7.2.在.bashrc文件中定义函数
解决退出shell函数消失的问题. 将函数定义在每次新shell启动时都会重新读取该函数的地方。 .bashrc文件,不管是交互式shell还是从现有shell启动的新shellbash shell在每次启动时都会在用户主目录中查找这个文件。
直接定义函数 直接在用户主目录的.bashrc文件中定义函数。将函数放在文件末尾.$ cat .bashrc
# .bashrc
# Source global definitions
if [ -r /etc/bashrc ]; then. /etc/bashrc
fi
function addem {echo $[ $1 $2 ]
}
$函数会在下次启动新的bash shell时生效。随后就能在系统中的任意地方使用这个函数。源引函数文件 只要是在shell脚本中就可以用source命令或别名即点号操作符将库文件中的函数添加到.bashrc脚本中.确保库文件的路径名正确.$ cat .bashrc
# .bashrc
# Source global definitions
if [ -r /etc/bashrc ]; then. /etc/bashrc
fi
. /home/rich/libraries/myfuncs
$shell会将定义好的函数传给子shell进程这些函数就能够自动用于该shell会话中的任何子shell脚本. 用源引库文件这些函数就可以在shell脚本中顺畅运行。
6.8.共享库函数
在开源世界中共享代码是必不可少的同样适用于shell脚本函数。可以下载各种shell脚本函数并将其用于自己的应用程序中。 下载、安装以及使用GNU shtool shell脚本函数库。shtool库提供了一些简单的shell脚本函数可用于实现日常的shell功能比如处理临时文件和目录、格式化输出显示等。
6.8.1.下载安装
将GNU shtool库下载并安装到你的系统中.wget http://ftp.gnu.org/gnu/shtool/shtool-2.0.8.tar.gz将文件复制到主目录中.使用tar命令提取文件.tar -zxvf shtool-2.0.8.tar.gz进入到解压新创建的目录构建库文件 使用标准的configure命令和make命令$ ./configure
$ makeconfigure命令会检查构建shtool库文件所必需的软件。发现了所需的工具会使用工具路径修改配置文件。 make命令负责构建shtool库文件。最终的shtool文件是一个完整的库软件包文件。 可以使用make命令测试库文件
$ make test
Running test suite:
echo...........ok
... ... 略
OK: passed: 19/19测试模式会测试shtool库中所有的函数。如果全部通过了测试就可以将库安装到Linux系统中的公用位置这样你的所有脚本就都能使用这个库了。 以root用户使用make命令的install选项完成安装.
# make install
Password:
./shtool mkdir -f -p -m 755 /usr/local
... ...
./shtool install -c -m 644 sh.version /usr/local/share/shtool/sh.version
./shtool install -c -m 644 sh.path /usr/local/share/shtool/sh.path# shtool -v
GNU shtool 2.0.8 (18-Jul-2008)安装成功,可以使用了.