Shell 脚本启动如何传递参数

我们在日常的脚本开发中,经常会碰到当脚本需要输入参数,然后脚本依据传递进来的参数作为依据,判断执行接下来的脚本逻辑。今天就介绍一下给Shell脚本传递参数进行交互的几种方式。

命令行参数

向脚本传递参数最基本的方式就是采用命令行参数。启动脚本时,通过命令行将参数传递给脚本。具体的格式如下:

./my_shell_script param1 param2 #param1,2作为参数,通过命令行启动脚本my_shell_script时传递给脚本。

那么脚本如何解析传递进来的参数呢?这点和我们常见的C/C++程序类似,有过C++ main函数编写经验的伙伴应该知道,我们启动main函数入口的exe 程序时,我们也采用类似的命令行参数传递方式,main函数接受传递进来的参数并放入参数数组中,其中exe文件的程序名会作为第一个参数放入参数数组中,而真正的函数参数会作为第二个元素放入数组中。在Shell 脚本中,参数解析是一样的,只是没有参数数组的概念。脚本中会将脚本文件名作为第一个参数,并用 $ 符号作为参数的引用。也就是说 $0 存储着程序名,$1 存储着脚本的第一个参数, $2 存储着脚本的第二个参数,以此类推直到 $9. 上例子:

Shell 脚本启动如何传递参数

图1

调用及输出为:

./my_script helle #启动脚本,并传递参数
the name of this/>the first parameter is helle
parameter 2 is null

示例比较简单,不解释了。值得注意的是,上面的例子中$0作为脚本名,获得是包含路径的字符串,如果希望只包含脚本文件名字而不包含路径信息,则可以通过 $(basename $0)来只截取脚本名字。其次,我们在使用参数时,应该对参数是否有效做判断,避免参数无效的情况。

bash>

移动变量

shift 命令用来移动参数变量,原理类似与数据结构中的具有FIFO特性的 queue, shift命令会让参数左移,例如执行一次shift 命令, $2会移动到$1, $3移动到$2,以此类推,这对于参数遍历,尤其不知道参数个数的情况下,非常有用。举例:

Shell 脚本启动如何传递参数

图2

调用及输出为:

./my_script I am fine
parameter #1 = I
parameter #2 = am
parameter #3 = fine

上图中可以看出,因为shift 命令,只用了$1变量,便实现了所有参数的遍历,

参数选项

我们知道Linux 命令中,很多带有参数选项,放在 '-'之后,例如 'ls -s',-s 就是命令ls的参数选项,那么我们编写的脚本也可以实现参数选项的格式。而这个关键在于如何解析传递进来的参数选项。下面就介绍一下具体的解析方法。

getopt 命令

getopt 命令是处理命令行选项和参数是非常便利的工具。格式为:

getopt optstring parameters

optstring是这条命令的关键,它定义了参数选项字母以及哪些选项字母需要参数值。

optstring 中列出所有选项字母,在需要参数值的选项字母后加一个冒号 ':' 作为标识。 例如

getopt ab:cd -a -b param1 -cd param2 param3
输出为:-a -b test1 -c -d -- param2 param3

这条命令的含义是:脚本包含4个参数选项,其中-b后需要传入参数值,-cd 被拆分成-c -d, 接着 '--' 双横线表示参数选项结束,其后面的param2 和 param3会作为参数传递给脚本。清楚了getopt 的规则后,我们看一下如何在脚本中使用。

脚本中使用 getopt 命令

Shell 脚本启动如何传递参数

图3

调用与输出:

 ./my_script -ab test1 -cd par1 par2
Found the -a option
Found the -b option and the parameter value is: 'test1'
Found the -c option
-d is not an option
Parameter #1: 'par1'
Parameter #2: 'par2'

脚本代码稍显复杂,我逐一讲解:

首先看第2行 'set -- $(getopt -q ab:cd "$@")', set命令我之前的文章有讲解过,该命令首先将脚本携带的命令选项和参数通过 getopt 格式化,然后将格式化的命令选项和参数通过set 设置为命令行值。有小伙伴注意到getopt 命令后面的 '-q',当输入getopt 没有定义的命令选项时,例如此处定义了ab:cd 四个命令选项,如果输入e选项,getopt会返回 invalid异常,-q 可以忽略这种异常。

接下来是一个while循环,循环里面是 case 分支语句,我们利用了shift 命令来保证新的参数只放在$1中,当遇到-a 选项时,执行对应的逻辑,此处我们输出"Found the -a option"。当遇到-b 选项时,因为后面需要参数值,我们此时通过$2来存储该参数值,并打印出来,注意:此处为什么是$2呢,因为在每次case语句结束时,我们在15行,用了shift 语句pop掉当前的参数。接下来‘--’分支代表命令行参数结束,后面的内容是脚本参数,所以此处shift掉--自身,迎接接下来的脚本参数。*) 表示case 的 default 语句,碰到没有定义的命令选项,提示"xx is not an option"

在后面就是处理脚本参数的逻辑,"$@"表示将脚本参数根据分隔符转化为 list 传递给脚本。然后便利该参数脚本,输出参数。

以上就是getopt 在脚本中基本的使用方式。

进阶的 getopts 命令

注意,此处是getopts 命令,它的用法和getopt相似,但是增加了一些更便利的规则,它的格式为

getopts optstring variable

optstring 与 getopt相似,不同的地方是 getopt中 -q 来忽略选项不存在的错误变换为在optstring 前面添加 ":" ,getopts 会将当前参数保存在variable中。该命令也会用到两个环境变量:OPTARG会保存命令选项后的参数值。OPTIND 会保存当前处理的参数位置。

Shell 脚本启动如何传递参数

图4

调用及输出为:

./my_script -ab test -cde p1 p2
Found the -a option
Found the -b option and the parameter value is: test
Found the -c option
d is not an option
? is not an option
Parameter #1: p1
Parameter #2: p2

图4的代码与图3相似,其中第二行改为getopts 来处理命令选项和参数,"getopts :ab:cd opt" 第一个冒号表示忽略不存在的选项异常,opt用来存储当前正在处理的参数值。case语句的每个分支中不需要‘-’开头,处理b 命令选项时,通过环境变量 ‘$OPTARG’来获取其后的参数值。 处理完命令选项后,要处理其后的参数,$OPTINT 存储和当前处理的参数位置,所以我们可以通过shift 命令跳转到参数的位置,然后就可以正常处理脚本参数了。

获得用户输入

有时脚本运行过程中,需要人来输入作为交互参数。具体方式包括:

read 命令

read variable #读取用户输入,并存储在variable中。
Shell 脚本启动如何传递参数

图5

调用与输出为:

./my_script
enter your name:Adam Kin
your name is Kin, Adam

超时处理

使用read命令时,如果一直没有用户输入,脚本执行就会悬停,如果希望不管有没有用户输入,脚本都能继续执行,那么可以通过 -t 指定超时时间,如果超时后仍无输入,脚本可以继续执行。

read -t 5 -p "enter your name:" name

以上面例子说明,当超过5秒没有输入后,read 返回非0码,脚本继续执行。

隐藏输入信息

linux中输入密码的时候,我们知道shell中是没有显示的,就是利用了隐藏读取输入的命令

read -s -p "enter your password" pass #-s会隐藏输入的信息。

具体例子就不列举了,比较简单,小伙伴可以自行在系统上尝试一下。


分享到:


相關文章: