您好, 欢迎来到 !    登录 | 注册 | | 设为首页 | 收藏本站

Shell 参数

1. Shell 参数概述

在 Shell 脚本编写中,我们为了使得程序灵活和无状态,有些变量我们不便于在脚本中写死,需要运用外部参数传递进去,每次传递的东西不一样,得到的结果也不尽相同,参数是与变量相辅相成的,将参数传递进 Shell 脚本中,也就成了变量,参数的使用使得我们的脚本更加的灵活和可扩展,同样也更易维护。

Shell 参数是我们在脚本外部传入的一系列参数,或是在 Shell 脚本中给传递的参数,其实质也就是上一节我们学习的变量,其与变量相辅相成,共同组成 Shell 脚本的一部分。

我们在变量一节知道了为什么利用变量,在此原因与变量类似,参数的使用使得我们的 Shell 脚本更加灵活,不需要在脚本中写死一些,根据的完成特定的,例如编写脚本计算 100 内数字的和,但是如果我们想计算 1000 呢?100000 呢?每次都需要脚本么,我们可以利用参数传递进计算脚本中,这样需要计算多少就由我们自己控制,这样的脚本也更加灵活,参数赋予脚本更强大的。

2. Shell 参数

我们知道了 Shell 中参数是什么,来看一下 Shell 脚本中参数的。

位置参数顾名思义,就是传递给脚本参数的位置,例如给脚本传递参数,我们可以在 Shell 脚本内部传入的位置参数,参数的格式为:$nn 代表数字。例如传递给脚本的第参数就为 $1,第 2 个参数就为 $2, 以此类推……,其中 $0 为该脚本的。

在我们讲解变量的时候,变量的一条规范就是名字不能以数字开头,在此就是为了避免与 Shell 的位置参数相同引发异常。

例如:

[root@master Shell_args]# cat args1.sh #!/bin/bashecho "第参数为: $1"echo "第二个参数为: $2"echo "脚本为: $0"[root@master Shell_args]# bash args1.sh python go第参数为: python
第二个参数为: go
脚本为: args1.sh

我们可以看到传递给 args1.sh 脚本两个位置参数,第为 python, 第二个为 go, 脚本为 args1.sh

在 Shell 中也存在特殊含义的参数如下表:

示例:

[root@master Shell_args]# cat args2.sh                 #!/bin/bashecho "第参数为: $1"echo "第二个参数为: $2"echo "脚本为: $0"echo "脚本接受参数总数为: $#"curl -I baidu.comecho "运行命令的状态为:$?"echo "脚本的ID为:$$"echo "\$*的结果为:$*"echo "\$@的结果为:$@"for i in "$*";doecho $idonefor j in "$@";do echo $jdone# 运行脚本来进行测试[root@master Shell_args]# bash args2.sh go python Shell第参数为: go
第二个参数为: python
脚本为: args2.sh
脚本接收参数总数为: 3
HTTP/1.1 200 OK
Date: Sun, 08 Mar 2020 07:32:22 GMT
Server: Apache
Last-Modified: Tue, 12 Jan 2010 13:48:00 GMT
ETag: "51-47cf7e6ee8400"Accept-Ranges: bytes
Content-Length: 81
Cache-Control: max-age=86400
Expires: Mon, 09 Mar 2020 07:32:22 GMT
Connection: Keep-Alive
Content-Type: text/html

运行命令的状态为:0
脚本的ID为:23333$*的结果为:go python Shell$@的结果为:go python Shell
go python Shell
go
python
Shell

我们能够通过上述例子看出,运行 curl -I baidu.com 的为 0,即为命令运行正常,到了正常的返回值;

$@$* 看上去很像,都是传递给脚本或的所有参数;

$* 当被双引号 " " 包含时,所有的位置参数被看做字符串,我们用 for 循环遍历的时候可以看到为一行;

$@当被双引号 " " 包含时,每个位置参数被看做独立的字符串,我们用 for 循环遍历的时候可以看到为每个字符串为单独的一行。

3. Shell 参数的使用

脚本传递参数,就是在运行脚本的时候通过位置参数传递进脚本内,每个参数利用空格来进行分割,如果传递的参数本身就有空格,则可以利用 "" 来引起来,作为整体传递,在脚本内通过 $n 来。

[root@master Shell_args]# cat args1.sh #!/bin/bashecho "第参数为: $1"echo "第二个参数为: $2"echo "脚本为: $0"[root@master Shell_args]# bash args1.sh go "python Shell java"第参数为: go
第二个参数为: python Shell java
脚本为: args1.sh

例如我们第二个参数为带有空格的多个字符串,我们可以用双引号引起来作为位置参数进行传入。

顾名思义,参数传递就是在外部进行参数的传入,由于部分在后续有专门章节详解,在此我们就以简单的示例进行说明。传递与脚本传递非常类似,只是在的时候进行传递位置参数即可,例如:

[root@master Shell_args]# cat args_fun.sh #!/bin/bash# 定义function show_args() {
        echo "第参数为: $1"echo "第二个参数为: $2"echo "脚本为: $0"}# show_args go Shell[root@master Shell_args]# bash args_fun.sh 第参数为: go
第二个参数为: Shell
脚本为: args_fun.sh

在示例中,我们可以看到没有通过在脚本外部进行参数传递,而是在 show_args 的时候传入来两个参数。

4. 实例

我们来做内网批量扫描可用 IP 脚本,用来判断某网段中的网络可达性。

可以利用 ping 命令来检测可以 ping 通的 IP,将返回正常的记录在 success.log 中,失败的记录在 fail.log 中。

传递两个参数,第参数为网络前缀,例如 192.168.0.,然后在脚本内部循环 1-255 来检测。

第二个参数为 ping 包的个数,如果包太多,时间花费太长,太短有可能造成误判,在此我们建议使用 2 个包来判断。

[root@master Shell_args]# cat ping.sh #!/bin/bash# Description: net check scripts# Auth: kaliarch# Email: kaliarch@163.com# function: net check# Date: 2020-03-08 14:00# Version: 1.0# 日志目录LOG_DIR="/tmp/netlog/"# 如果日志目录不存在则创建[ ! - ${LOG_DIR} ] && mkdir -p ${LOG_DIR}# 定义成功与失败日志SUCCESS_LOGFILE="success.log"FAIL_LOGFILE="fail.log"# 网络前缀NET_PREFIX=$# 检测包PACKAGE_NUM=$for num in `seq  `;do# 进行ping检测echo "check ${NET_PREFIX}${num}..."ping - ${PACKAGE_NUM} ${NET_PREFIX}${num} &>/dev/null# 如果返回正常则记录可以ping通的ip到successlog中[ $? -eq  ] && echo ${NET_PREFIX}${num} >> ${LOG_DIR}${SUCCESS_LOGFILE} || echo ${NET_PREFIX}${num} >> ${LOG_DIR}${FAIL_LOGFILE}
done# 测试[root@master Shell_args]# bash ping.sh 172.16.60. 2check ....check ....check ....check ....check ....check ....

当脚本运行完成后,可以在 /tmp/netlog/ 目录下查看成功与失败的 IP 信息。

5. 注意事项

需要在实战中理解参数的特殊用处,在编写脚本中尽可能多用参数,使得脚本无状态;

需要理解 $@$* 两个的不同之处,在使用循环的时候需要格外注意;

在利用位置参数传入脚本的时候,最好利用变量去接收传递的外部位置参数,便于我们在脚本内识别参数的具体含义。

6. 小结

参数与变量是相辅相成的,将变量传递进脚本或就为参数,脚本与变量配合使得我们的脚本更加通用,适应更广的需求。需要牢记特殊参数的形式,在后期的 Shell 编程中,这些参数是脚本编程的基石,只有基础牢靠,后续的使用才会得心应手,对上述的例子可以举一反三,例如探测某 IP 的所有端口是否开放等,在实际应用场景中熟悉各种参数的。


联系我
置顶