@@ -38,14 +38,7 @@ $ /bin/sh ./script.sh
3838$ bash ./script.sh
3939```
4040
41- ## 执行权限和路径fn () {
42- local foo
43- foo=1
44- echo "fn: foo = $foo"
45- }
46-
47- fn
48- echo "global: foo = $foo"
41+ ## 执行权限和路径
4942
5043前面说过,通过 Shebang 行指定解释器的脚本,可以直接执行。这有一个前提条件,就是脚本需要有执行权限。可以使用下面的命令,赋予脚本执行权限。
5144
@@ -161,6 +154,8 @@ $ script.sh word1 word2 word3
161154
162155如果脚本的参数多于9个,那么第10个参数可以用` ${10} ` 的形式引用,以此类推。
163156
157+ 注意,如果命令是` command -o foo bar ` ,那么` -o ` 是` $1 ` ,` foo ` 是` $2 ` ,` bar ` 是` $3 ` 。
158+
164159下面是一个脚本内部读取命令行参数的例子。
165160
166161``` bash
@@ -198,6 +193,10 @@ done
198193
199194上面例子中,` $@ ` 返回一个全部参数的列表,然后使用` for ` 循环遍历。
200195
196+ ## shift 命令
197+
198+ ` shift ` 命令可以改变脚本参数,每次执行都会移除脚本当前的第一个参数(` $1 ` ),使得后面的参数向前一位,即` $2 ` 变成` $1 ` 、` $3 ` 变成` $2 ` 、` $4 ` 变成` $3 ` ,以此类推。
199+
201200` while ` 循环结合` shift ` 命令,也可以读取每一个参数。
202201
203202``` bash
@@ -206,13 +205,61 @@ done
206205echo " 一共输入了 $# 个参数"
207206
208207while [ " $1 " != " " ]; do
209- echo " 剩下 $# 个参数"
210- echo " 参数:$1 "
211- shift
208+ echo " 剩下 $# 个参数"
209+ echo " 参数:$1 "
210+ shift
211+ done
212+ ```
213+
214+ 上面例子中,` shift ` 命令每次移除当前第一个参数,从而通过` while ` 循环遍历所有参数。
215+
216+ ` shift ` 命令可以接受一个整数作为参数,指定所要移除的参数个数,默认为` 1 ` 。
217+
218+ ``` bash
219+ shift 3
220+ ```
221+
222+ 上面的命令移除前三个参数,原来的` $4 ` 变成` $1 ` 。
223+
224+ ## getopts 命令
225+
226+ ` getopts ` 命令用来解析复杂的命令行参数,通常与` while ` 循环一起使用,取出所有的带有前置连词线(` - ` )的参数。
227+
228+ 它带有两个参数。第一个参数是字符串,给出所有的连词线参数。如果该参数带有参数值,则后面必须带有一个冒号(` : ` )。比如,某个命令可以有三个参数` -l ` 、` -h ` 、` -a ` ,其中只有` -a ` 可以带有参数值,那么` getopts ` 的第一个参数写成` lha: ` ,顺序不重要,注意` a ` 后面有一个冒号。` getopts ` 的第二个参数是一个变量名,用来保存参数。
229+
230+ 下面是一个例子。
231+
232+ ``` bash
233+ while getopts ' lha:' OPTION; do
234+ case " $OPTION " in
235+ l)
236+ echo " linuxconfig"
237+ ;;
238+
239+ h)
240+ echo " h stands for h"
241+ ;;
242+
243+ a)
244+ avalue=" $OPTARG "
245+ echo " The value provided is $OPTARG "
246+ ;;
247+ ? )
248+ echo " script usage: $( basename $0 ) [-l] [-h] [-a somevalue]" >&2
249+ exit 1
250+ ;;
251+ esac
212252done
253+ shift " $(( $OPTIND - 1 )) "
213254```
214255
215- 上面例子中,` shift ` 命令的作用是移除当前第一个参数,即` $2 ` 变成` $1 ` 、` $3 ` 变成` $2 ` 、` $4 ` 变成` $3 ` ,以此类推。
256+ 上面例子中,` while ` 循环不断执行` getopts 'lha:' OPTION ` 命令,每次执行就会读取一个连词线参数(以及对应的参数值),然后进入循环体。变量` OPTION ` 保存的是,当前处理的那一个连词线参数(即` l ` 、` h ` 或` a ` )。如果用户输入了没有指定的参数(比如` -x ` ),那么` OPTION ` 等于` ? ` 。循环体内使用` case ` 判断,处理这四种不同的情况。
257+
258+ 如果某个连词线参数带有参数值,比如` -a foo ` ,那么处理` a ` 参数的时候,变量` $OPTARG ` 保存的就是参数值。
259+
260+ 注意,只要遇到不带连词线的参数,` getopts ` 就会执行失败,从而退出` while ` 循环。比如,` getopts ` 可以解析` command -l foo ` ,但不可以解析` command foo -l ` 。另外,多个连词线参数写在一起的形式,比如` command -lh ` ,` getopts ` 也可以正确处理。
261+
262+ 变量` $OPTIND ` 在` getopts ` 开始执行前是` 1 ` ,然后每次执行就会加` 1 ` 。等到退出` while ` 循环,就意味着连词线参数全部处理完毕。这时,` $OPTIND - 1 ` 就是已经处理的连词线参数个数,使用` shift ` 命令将这些参数移除,保证后面的代码可以用` $1 ` 、` $2 ` 等处理命令的主参数。
216263
217264## 别名
218265
351398
352399## 命令执行结果
353400
354- 命令执行结束后,会有一个返回值。` 0 ` 表示执行成功,非` 0 ` (通常是` 1 ` )表示执行失败。
401+ 命令执行结束后,会有一个返回值。` 0 ` 表示执行成功,非` 0 ` (通常是` 1 ` )表示执行失败。环境变量 ` $? ` 可以读取前一个命令的返回值。
355402
356403利用这一点,可以在脚本中对命令执行结果进行判断。
357404
@@ -388,3 +435,7 @@ cd $some_directory && rm *
388435cd $some_directory || exit 1
389436```
390437
438+ ## 参考链接
439+
440+ - [ How to use getopts to parse a script options] ( https://linuxconfig.org/how-to-use-getopts-to-parse-a-script-options ) , Egidio Docile
441+
0 commit comments