shell 函数
函数(function)是可以重复使用的代码片段,有利于代码的复用。它与别名(alias)的区别是,别名只适合封装简单的单个命令,函数则可以封装复杂的多行命令。
函数总是在当前 Shell 执行,这是跟脚本的一个重大区别,Bash 会新建一个子 Shell 执行脚本。如果函数与脚本同名,函数会优先执行。但是,函数的优先级不如别名,即如果函数与别名同名,那么别名优先执行。
Bash 函数定义的语法有两种。
# 第一种
fn() {
# codes
}
# 第二种
function fn() {
# codes
}
参数变量
函数体内可以使用参数变量,获取函数参数。函数的参数变量,与脚本参数变量是一致的。
$1~$9:函数的第一个到第9个的参数。
$0:函数所在的脚本名。
$#:函数的参数总数。
$@:函数的全部参数,参数之间使用空格分隔。
$*:函数的全部参数,参数之间使用变量$IFS值的第一个字符分隔,默认为空格,但是可以自定义。
如果函数的参数多于9个,那么第10个参数可以用${10}的形式引用,以此类推。
hello() {
echo "Hello $1"
}
上面代码中,函数体里面的$1表示函数调用时的第一个参数。
调用时,就直接写函数名,参数跟在函数名后面。
$ hello world
Hello world
下面是一个多行函数的例子,显示当前日期时间。
today() {
echo -n "Today's date is: "
date +"%A, %B %-d, %Y"
}
return命令用于从函数返回一个值。函数执行到这条命令,就不再往下执行了,直接返回了。
function func_return_value {
return 10
}
函数将返回值返回给调用者。如果命令行直接执行函数,下一个命令可以用$?拿到返回值。
$ func_return_value
$ echo "Value returned by function is: $?"
Value returned by function is: 10
return后面不跟参数,只用于返回也是可以的。
function name {
commands
return
}
Bash 函数体内直接声明的变量,属于全局变量,整个脚本都可以读取。这一点需要特别小心。
函数体内不仅可以声明全局变量,还可以修改全局变量。
#! /bin/bash
foo=1
fn () {
foo=2
}
fn
echo $foo
函数里面可以用local命令声明局部变量。 local 变量名
#! /bin/bash
# 脚本 test.sh
fn () {
local foo
foo=1
echo "fn: foo = $foo"
}
fn
echo "global: foo = $foo"
向函数传递数组/函数返回数组
1、向函数传递数组 使用 “$@”(全部参数)
函数调用时,直接写函数名,参数跟在函数名后面。
function array(){
for i in "$@"
do
echo ${i}
done
}
#调用函数:
a=(1 3 5 6)
ayrray ${a[*]}
- 函数返回数组
在函数内部 echo ${array[*]}
然后 arry=函数名 输入参数
就将echo的数组赋值给arry
function array(){
echo new value:${newwarray[*]}
}
result = `array`
数组
创建数组
数组可以采用逐个赋值的方法创建。
ARRAY[INDEX]=value
上面语法中,ARRAY是数组的名字,可以是任意合法的变量名。INDEX是一个大于或等于零的整数,也可以是算术表达式。注意数组第一个元素的下标是0, 而不是1。
下面创建一个三个成员的数组。
$ array[0]=val
$ array[1]=val
$ array[2]=val
数组也可以采用一次性赋值的方式创建。
ARRAY=(value1 value2 ... valueN)
# 等同于
ARRAY=(
value1
value2
value3
)
采用上面方式创建数组时,可以按照默认顺序赋值,也可以在每个值前面指定位置。
$ array=(a b c)
$ array=([2]=c [0]=a [1]=b)
$ days=(Sun Mon Tue Wed Thu Fri Sat)
$ days=([0]=Sun [1]=Mon [2]=Tue [3]=Wed [4]=Thu [5]=Fri [6]=Sat)
只为某些值指定位置,也是可以的。
names=(hatter [5]=duchess alice)
上面例子中,hatter是数组的0号位置,duchess是5号位置,alice是6号位置。
没有赋值的数组元素的默认值是空字符串。
定义数组的时候,可以使用通配符。
$ mp3s=( *.mp3 )
上面例子中,将当前目录的所有 MP3 文件,放进一个数组。
先用declare -a命令声明一个数组,也是可以的。
$ declare -a ARRAYNAME
read -a命令则是将用户的命令行输入,存入一个数组。
$ read -a dice
上面命令将用户的命令行输入,存入数组dice。
读取数组
读取数组指定位置的成员,要使用下面的语法。
$ echo ${array[i]} # i 是索引
上面语法里面的大括号是必不可少的,否则 Bash 会把索引部分[i]按照原样输出。
读取所有成员
@和*是数组的特殊索引,表示返回数组的所有成员。
$ foo=(a b c d e f)
$ echo ${foo[@]}
a b c d e f
这两个特殊索引配合for循环,就可以用来遍历数组。
for i in "${names[@]}"; do
echo $i
done
如果读取数组成员时,没有读取指定哪一个位置的成员,默认使用0号位置。
$ declare -a foo
$ foo=A
$ echo ${foo[0]}
A
上面例子中,foo是一个数组,赋值的时候不指定位置,实际上是给foo[0]赋值。
$ foo=(a b c d e f)
$ echo ${foo}
a
$ echo $foo
a
要想知道数组的长度(即一共包含多少成员),可以使用下面两种语法。
${#array[*]}
${#array[@]}
下面是一个例子。
$ a[100]=foo
$ echo ${#a[*]}
1
$ echo ${#a[@]}
1
${!array[@]}或${!array[*]},可以返回数组的成员序号,即哪些位置是有值的。
$ arr=([5]=a [9]=b [23]=c)
$ echo ${!arr[@]}
5 9 23
$ echo ${!arr[*]}
5 9 23
${array[@]:position:length}的语法可以提取数组成员。
数组末尾追加成员,可以使用+=赋值运算符。它能够自动地把值追加到数组末尾。否则,就需要知道数组的最大序号,比较麻烦。
$ foo=(a b c)
$ echo ${foo[@]}
a b c
$ foo+=(d e f)
$ echo ${foo[@]}
a b c d e f
sleep num
程序暂停num秒