本文介绍 shell script 中变量的高阶用法,包括参数解析与变量读取。

1. Shell 自定义函数

除了 Shell 自带命令之外,Shell 也支持自定义函数。好处是代码复用,方便修改。

[function] fun_name[()]
{
    echo $0
    echo $1
    [return x]
}
  • 函数名需要满足变量名一样的规则
  • 函数名前面的 function 关键字可要可不要,函数名后面的 () 可要可不要,{} 是必要的
  • 最后的 return x 可要可以不要,如果没有,就以最后一行命令的返回值作为整个函数的返回值,函数返回值只能是数字
  • 函数参数数目可以不确定,可以是任意多个

在函数内部,则用 $0 $2$n 的方式来访问变量。也可用 $@$* 的方式来表示所有参数。

fun_name arg1 arg2 arg3

2. 参数传递解析

Shell 脚本在执行时候可以传递参数,实现不同参数输出不同结构。

bash xxx.sh arg1 arg2
变量含义
$n传递给脚本或函数的参数,n 是一个数字,表示从零开始第 n 个参数,第一个参数是 $1
$0当前脚本的文件名,shell script 第零个参数
$#传递给脚本或函数的参数个数
$*传递给脚本或函数的所有参数
$@传递给脚本或函数的所有参数
$?上个命令的退出状态,或函数的返回值
$$当前 Shell 进程 ID。对于 shell script,就是这些脚本所在的进程 ID

$*$@ 都表示传递给函数或脚本的所有参数。

  • 不被双引号(” “)包含时,都以 "$1" "$2" … "$n" 的形式输出所有参数。
  • 当它们被双引号(” “)包含时:
    • "$*" 会将所有的参数作为一个整体,以 "$1 $2 … $n" 的形式输出所有参数
    • "$@" 会将各个参数分开,以 "$1" "$2""$n" 的形式输出所有参数

参数解析没有顺序,没有 Python argparse 的位置参数和可选参数之分,得到的结果就是一个 list,所有的参数解析就是对 list 中结果进行匹配。其中带有 - 和不带有 - 的变量是不一样的。

  1. 判断命令是否有参数
if [ $# -lt 1 ];
then
echo "no arguments"
else
echo "has $# args"
fi
  1. 判断命令是否带有某个特定参数
j="-x"
for i in $@;
do
if [ $i = $j ];
then
echo "has $j"
fi
done

3. 文件包含

常常有这样的需求,在一个文件中定义了一个函数,要在另外一个文件中调用。此时用 source 或者 . 就可以了。

# funa in a.sh
funa {
     echo "funa"
}

b.sh 中要调用 a.shfuna,则是:

. a.sh
funa

4. 总结

本文介绍了 Shell 中的函数定义和使用方式。