|
| 1 | +# Bash 函数 |
| 2 | + |
| 3 | +## 简介 |
| 4 | + |
| 5 | +函数(function)是可以重复使用的代码片段,有利于代码的复用。它与别名(alias)的区别是,别名只适合封装简单的单个命令,函数则可以封装复杂的多行命令。 |
| 6 | + |
| 7 | +函数总是在当前 Shell 执行,这是跟脚本的一个重大区别。如果函数与脚本同名,函数会优先执行。但是,函数的优先级不如别名,即如果函数与别名同名,那么别名优先执行。 |
| 8 | + |
| 9 | +Bash 函数定义的语法有两种。 |
| 10 | + |
| 11 | +```bash |
| 12 | +# 第一种 |
| 13 | +fn() { |
| 14 | + # codes |
| 15 | +} |
| 16 | + |
| 17 | +# 第二种 |
| 18 | +function fn() { |
| 19 | + # codes |
| 20 | +} |
| 21 | +``` |
| 22 | + |
| 23 | +上面代码中,`fn`是自定义的函数名,函数代码就写在大括号之中。这两种定义函数的写法是等价的。 |
| 24 | + |
| 25 | +下面是一个简单函数的例子。 |
| 26 | + |
| 27 | +```bash |
| 28 | +hello() { |
| 29 | + echo "Hello $1"; |
| 30 | +} |
| 31 | +``` |
| 32 | + |
| 33 | +上面代码中,函数体里面的`$1`表示函数调用时的第一个参数。 |
| 34 | + |
| 35 | +调用时,可以直接执行函数名,参数跟着函数名后面。 |
| 36 | + |
| 37 | +```bash |
| 38 | +$ hello world |
| 39 | +hello world |
| 40 | +``` |
| 41 | + |
| 42 | +下面是一个多行函数的例子,显示当前日期时间。 |
| 43 | + |
| 44 | +```bash |
| 45 | +today() { |
| 46 | + echo -n "Today's date is: " |
| 47 | + date +"%A, %B %-d, %Y" |
| 48 | +} |
| 49 | +``` |
| 50 | + |
| 51 | +查看当前 Shell 已经定义的所有函数,可以使用`declare`命令。 |
| 52 | + |
| 53 | +```bash |
| 54 | +$ declare -f |
| 55 | +``` |
| 56 | + |
| 57 | +上面的`declare`命令不仅会输出函数名,还会输出所有定义。输出顺序是按照函数名的字母表顺序。由于会输出很多内容,最好通过管道命令配合`more`或`less`使用。 |
| 58 | + |
| 59 | +`declare`命令还支持查看单个函数的定义。 |
| 60 | + |
| 61 | +```bash |
| 62 | +$ declare -f functionName |
| 63 | +``` |
| 64 | + |
| 65 | +`declare -F`可以输出所有已经定义的函数名,不含函数体。 |
| 66 | + |
| 67 | +```bash |
| 68 | +$ declare -F |
| 69 | +``` |
| 70 | + |
| 71 | +删除一个函数,可以使用`unset`命令。 |
| 72 | + |
| 73 | +```bash |
| 74 | +unset -f functionName |
| 75 | +``` |
| 76 | + |
| 77 | +## 参数变量 |
| 78 | + |
| 79 | +函数体内可以使用参数变量,获取外部参数。函数的参数变量,与脚本参数变量是一致的。 |
| 80 | + |
| 81 | +- `$1`~`$9`:函数的第一个到第9个的参数。 |
| 82 | +- `$0`:函数所在的脚本名。 |
| 83 | +- `$#`:函数的参数总数。 |
| 84 | +- `$a`:函数的全部参数,参数之间使用空格分隔。 |
| 85 | +- `$*`:函数的全部参数,参数之间使用变量`$IFS`值的第一个字符分隔,默认为空格,但是可以自定义。 |
| 86 | + |
| 87 | +如果函数的参数多于9个,那么第10个参数可以用`${10}`的形式引用,以此类推。 |
| 88 | + |
| 89 | +下面是一个示例脚本`test.sh`。 |
| 90 | + |
| 91 | +```bash |
| 92 | +# 脚本文件 test.sh |
| 93 | +function alice { |
| 94 | + echo "alice: $@" |
| 95 | + echo "$0: $1 $2 $3 $4" |
| 96 | + echo "$# arguments" |
| 97 | + |
| 98 | +} |
| 99 | + |
| 100 | +alice in wonderland |
| 101 | +``` |
| 102 | + |
| 103 | +运行该脚本,结果如下。 |
| 104 | + |
| 105 | +```bash |
| 106 | +$ bash test.sh |
| 107 | +alice: in wonderland |
| 108 | +test.sh: in wonderland |
| 109 | +2 arguments |
| 110 | +``` |
| 111 | + |
| 112 | +上面这个例子中,由于函数`alice`只有第一个和第二个参数,所以第三个和第四个参数为空。 |
| 113 | + |
| 114 | +下面是一个日志函数的例子。 |
| 115 | + |
| 116 | +```bash |
| 117 | +function log_msg { |
| 118 | + echo "[`date '+ %F %T'` ]: $@" |
| 119 | +} |
| 120 | +``` |
| 121 | + |
| 122 | +使用方法如下。 |
| 123 | + |
| 124 | +```bash |
| 125 | +$ log_msg "This is sample log message" |
| 126 | +[ 2018-08-16 19:56:34 ]: This is sample log message |
| 127 | +``` |
| 128 | + |
| 129 | +## 返回值 |
| 130 | + |
| 131 | +`return`命令用于从函数返回一个值。 |
| 132 | + |
| 133 | +```bash |
| 134 | +function func_return_value { |
| 135 | + return 10 |
| 136 | +} |
| 137 | +``` |
| 138 | + |
| 139 | +函数将返回值返回给调用者。如果命令行直接执行函数,下一个命令可以用`$?`拿到返回值。 |
| 140 | + |
| 141 | +```bash |
| 142 | +$ func_return_value |
| 143 | +$ echo "Value returned by function is: $?" |
| 144 | +Value returned by function is: 10 |
| 145 | +``` |
| 146 | + |
| 147 | +## 全局变量和局部变量 |
| 148 | + |
| 149 | +Bash 函数体内直接声明的变量,属于全局变量,整个脚本都可以读取。这一点需要特别小心。 |
| 150 | + |
| 151 | +```bash |
| 152 | +# 脚本 test.sh |
| 153 | +fn () { |
| 154 | + foo=1 |
| 155 | + echo "fn: foo = $foo" |
| 156 | +} |
| 157 | + |
| 158 | +fn |
| 159 | +echo "global: foo = $foo" |
| 160 | +``` |
| 161 | + |
| 162 | +上面脚本的运行结果如下。 |
| 163 | + |
| 164 | +```bash |
| 165 | +$ bash test.sh |
| 166 | +fn: foo = 1 |
| 167 | +global: foo = 1 |
| 168 | +``` |
| 169 | + |
| 170 | +上面例子中,变量`$foo`是在函数`fn`内部声明的,函数体外也可以读取。 |
| 171 | + |
| 172 | +函数体内不仅可以声明全局变量,还可以修改全局变量。 |
| 173 | + |
| 174 | +```bash |
| 175 | +foo=1 |
| 176 | + |
| 177 | +fn () { |
| 178 | + foo=2 |
| 179 | +} |
| 180 | + |
| 181 | +echo $foo |
| 182 | +``` |
| 183 | + |
| 184 | +上面代码执行后,输出的变量`$foo`值为2。 |
| 185 | + |
| 186 | +函数里面可以用`local`命令声明局部变量。 |
| 187 | + |
| 188 | +```bash |
| 189 | +# 脚本 test.sh |
| 190 | +fn () { |
| 191 | + local foo |
| 192 | + foo=1 |
| 193 | + echo "fn: foo = $foo" |
| 194 | +} |
| 195 | + |
| 196 | +fn |
| 197 | +echo "global: foo = $foo" |
| 198 | +``` |
| 199 | + |
| 200 | +上面脚本的运行结果如下。 |
| 201 | + |
| 202 | +```bash |
| 203 | +$ bash test.sh |
| 204 | +fn: foo = 1 |
| 205 | +global: foo = |
| 206 | +``` |
| 207 | + |
| 208 | +上面例子中,`local`命令声明的`foo`变量,只在函数体内有效,函数体外没有定义。 |
| 209 | + |
| 210 | +## 参考链接 |
| 211 | + |
| 212 | +- [How to define and use functions in Linux Shell Script](https://www.linuxtechi.com/define-use-functions-linux-shell-script/), by Pradeep Kumar |
0 commit comments