shell脚本读取命令行的参数
转至:https://www.cnblogs.com/eternityz/p/13879836.html
前提
在编写shell程序时经常需要处理命令行参数
选项与参数:
如下命令行:
- ./test.sh -f config.conf -v --prefix=/home
-f为选项,它需要一个参数,即config.conf,
-v 也是一个选项,但它不需要参数。
--prefix我们称之为一个长选项,即选项本身多于一个字符,它也需要一个参数,用等号连接,当然等号不是必须的,
/home可以直接写在--prefix后面,即--prefix/home,
更多的限制后面具体会讲到。
一.手工处理方式(已验证)
在手工处理方式中,首先要知道几个变量,还是以上面的命令行为例:
$0:./test.sh,即命令本身,相当于c/c++中的argv[0]
$1:-f,第一个参数.
$2:config.conf
$3, $4 ... :类推。
$#: 参数的个数,不包括命令本身,上例中$#为4.
$@:参数本身的列表,也不包括命令本身,如上例为 -f config.conf -v --prefix=/home
$*:和$@相同,但"$*" 和 "$@"(加引号)并不同,"$*"将所有的参数解释成一个字符串,而"$@"是一个参数数组。
例子
- #!/bin/bash
- for arg in "$*"
- do
- echo $arg
- done
- for arg in "$@"
- do
- echo $arg
- done
执行./test.sh -f config.conf -n 10 会打印:
- #./test.sh -f config.conf -n 10
- # 这是"$*"的输出
- -f config.conf -n 10
- #以下为$@的输出
- -f
- config.conf
- -n
- 10
所以,手工处理的方式即对这些变量的处理。因为手工处理高度依赖于你在命令行上所传参数的位置,所以一般都只用来处理较简单的参数。
例如:
- ./test.sh 10
而很少使用./test -n 10这种带选项的方式。
典型用法为:
- #!/bin/bash
- if [ x$1 != x ]
- then
- #...有参数逻辑
- else
- then
- #...没有参数逻辑
- fi
为什么要使用 x$1 != x 这种方式来比较呢?(x就是任意的一个字符,也可以是别的)
想像一下这种方式比较:
- if [ -n $1 ] #$1不为空
但如果用户不传参数的时候,$1为空,这时就会变成 [ -n ] ,所以需要加一个辅助字符串来进行比较。
手工处理方式能满足大多数的简单需求,配合shift使用也能构造出强大的功能,但在要处理复杂选项的时候建议用下面的两种方法。
二.getopts/getopt
处理命令行参数是一个相似而又复杂的事情,为此,c提供了getopt/getopt_long等函数,
c++的boost提供了options库,在shell中,处理此事的是getopts和getopt.
getopts和getopt功能相似但又不完全相同,其中getopt是独立的可执行文件,而getopts是由bash内置的。
- ./test.sh -a -b -c : 短选项,各选项不需参数
- ./test.sh -abc : 短选项,和上一种方法的效果一样,只是将所有的选项写在一起。
- ./test.sh -a args -b -c :短选项,其中-a需要参数,而-b -c不需参数。
- ./test.sh --a-long=args --b-long :长选项
先来看getopts,它不支持长选项。
使用getopts非常简单:
- #test.sh
- #!/bin/bash
- while getopts "a:bc" arg #选项后面的冒号表示该选项需要参数
- do
- case $arg in
- a)
- echo "a's arg:$optarg" #参数存在$optarg中
- b)
- echo "b"
- c)
- echo "c"
- ?) #当有不认识的选项的时候arg为?
- echo "unkonw argument"
- exit 1
- esac
- done
现在就可以使用:
- ./test.sh -a arg -b -c
或
- ./test.sh -a arg -bc
来加载了。
应该说绝大多数脚本使用该函数就可以了,如果需要支持长选项以及可选参数,那么就需要使用getopt.
getopt自带的一个例子:
- #!/bin/bash
- # a small example program for using the new getopt(1) program.
- # this program will only work with bash(1)
- # an similar program using the tcsh(1) script language can be found
- # as parse.tcsh
- # example input and output (from the bash prompt):
- # ./parse.bash -a par1 'another arg' --c-long 'wow!*\?' -cmore -b " very long "
- # option a
- # option c, no argument
- # option c, argument `more'
- # option b, argument ` very long '
- # remaining arguments:
- # --> `par1'
- # --> `another arg'
- # --> `wow!*\?'
- # note that we use `"$@"' to let each command-line parameter expand to a
- # separate word. the quotes around `$@' are essential!
- # we need temp as the `eval set --' would nuke the return value of getopt.
- #-o表示短选项,两个冒号表示该选项有一个可选参数,可选参数必须紧贴选项
- #如-carg 而不能是-c arg
- #--long表示长选项
- #"$@"在上面解释过
- # -n:出错时的信息
- # -- :举一个例子比较好理解:
- #我们要创建一个名字为 "-f"的目录你会怎么办?
- # mkdir -f #不成功,因为-f会被mkdir当作选项来解析,这时就可以使用
- # mkdir -- -f 这样-f就不会被作为选项。
- temp=`getopt -o ab:c:: --long a-long,b-long:,c-long:: \
- -n 'example.bash' -- "$@"`
- if [ $? != 0 ] ; then echo "terminating..." >&2 ; exit 1 ; fi
- # note the quotes around `$temp': they are essential!
- #set 会重新排列参数的顺序,也就是改变$1,$2...$n的值,这些值在getopt中重新排列过了
- eval set -- "$temp"
- #经过getopt的处理,下面处理具体选项。
- while true ; do
- case "$1" in
- -a|--a-long) echo "option a" ; shift ;;
- -b|--b-long) echo "option b, argument \`$2'" ; shift 2 ;;
- -c|--c-long)
- # c has an optional argument. as we are in quoted mode,
- # an empty parameter will be generated if its optional
- # argument is not found.
- case "$2" in
- "") echo "option c, no argument"; shift 2 ;;
- *) echo "option c, argument \`$2'" ; shift 2 ;;
- esac ;;
- --) shift ; break ;;
- *) echo "internal error!" ; exit 1 ;;
- esac
- done
- echo "remaining arguments:"
- for arg do
- echo '--> '"\`$arg'" ;
- done
比如使用
- ./test -a -b arg arg1 -c
你可以看到,命令行中多了个arg1参数,在经过getopt和set之后,命令行会变为:
- -a -b arg -c -- arg1
1指向−a, 1指向−a, 2指向-b,3指向arg, 3指向arg, 4指向-c,$5指向--,而多出的arg1则被放到了最后。
三.总结
一般小脚本手工处理也就够了,getopts能处理绝大多数的情况,getopt较复杂,功能也更强大。
站在巨人肩膀上摘苹果
shell脚本读取命令行的参数的更多相关文章
- Shell脚本中判断输入参数个数的方法投稿:junjie 字体:[增加 减小] 类型:转载
Shell脚本中判断输入参数个数的方法 投稿:junjie 字体:[增加 减小] 类型:转载 这篇文章主要介绍了Shell脚本中判断输入参数个数的方法,使用内置变量$#即可实现判断输入了多少个参数 ...
- Shell脚本编写3---Shell 传递参数
我们可以在执行 Shell 脚本时,向脚本传递参数,脚本内获取参数的格式为:$n.n 代表一个数字,1 为执行脚本的第一个参数,2 为执行脚本的第二个参数,以此类推…… 执行脚本,查看输出结果: 另外 ...
- awk如何区分shell脚本传进来的参数和自身的参数?awk如何获取shell脚本传进来的参数;awk中如何执行shell命令
问题:对于shell脚本,$0表示脚本本身,$1表示脚本的第一个参数,$2……依次类推:对于awk,$1表示分割后的第一个字段,$2……依次类推.那么对于shell脚本中的awk如何区分两者呢? 答案 ...
- 【转】shell脚本中如何传入参数
(1)直接用$1,$2取传入的参数vim /root/test.sh#!/bin/bashif [ $1 == "start" ] then echo "do ...
- 【shell脚本】优化内核参数===
一.Linux内核参数优化 Sysctl命令用来配置与显示在/proc/sys目录中的内核参数.如果想使参数长期保存,可以通过编辑/etc/sysctl.conf文件来实现. 命令格式: sysct ...
- shell脚本获取传递的参数
1 脚本编写 #!/bin/bash 2 解释 $n 表示是第几个参数 $0 表示脚本命令本身 3 执行效果
- 编写SHELL脚本--判断用户的参数
测试语句格式: [ 条件表达式 ] 常见的几种形式: [ -d /etc ] 判断/etc是不是一个目录类型, [ -e /etc/php.ini ] 判断/etc/php.ini 文件是否存在 [ ...
- [shell]shell脚本传入不固定参数的写法,如--help等
最近在调试一个wifi模块,需要传一些不固定的参数,一下一个参数解析的函数可以搞定这个事情,里面内容好多部分是从一个example中剽窃而来(窃喜) #!/bin/bash # writen by a ...
- Linux程序设计 读笔2 Shell脚本
第二章 Shell程序设计 四.管道和重定向 1 重定向输出 ls -l > lsoutput.txt ps >> lsoutput.txt >>表示附加到一个文件中 文 ...
随机推荐
- POXSIX之信号量
#include<stdio.h> #include<semaphore.h> #include<fcntl.h> #include<stdlib.h> ...
- python 线程池使用
传统多线程方案会使用"即时创建, 即时销毁"的策略.尽管与创建进程相比,创建线程的时间已经大大的缩短,但是如果提交给线程的任务是执行时间较短,而且执行次数极其频繁,那么服务器将处于 ...
- SQL查询字段,起别名,列参与数学运算
13.简单查询 13.1.查询一个字段? select 字段名 from 表名: 其中要注意: select和from都是关键字 字段名和表名都是标识符. 强调: 对于SQL语句说,是通用的 所有的S ...
- 谷歌浏览器和火狐浏览器如何查看HTTP协议
谷歌浏览器和火狐浏览器如何查看HTTP协议 谷歌浏览器查看HTTP协议 火狐浏览器查看HTTP协议
- java-异常概述及体系
1 package p1.exception; 2 3 4 /* 5 * 异常:是在运行时期发生的不正常情况. 6 * 7 * 8 * 在java中用类的形式对不正常情况进行了描述和封装对象. 9 * ...
- 图文并茂理解iptables
原文地址:http://www.zsythink.net/archives/1199 以下是转载内容: iptables详解:图文并茂理解iptables | 朱双印博客 这篇文章会尽量以通俗易懂的方 ...
- 业务驱动的全景监控体系在阿里的应用 | 阿里巴巴DevOps实践指南
编者按:本文源自阿里云云效团队出品的<阿里巴巴DevOps实践指南>,扫描上方二维码或前往:https://developer.aliyun.com/topic/devops,下载完整版电 ...
- 学习JAVAWEB第十八天
今天解决了登录过程中的数据库连接池的一些问题,如本地服务器不能被访问,主要是连接池的配置文件的问题 明天做一个htm页面,不同用户的不同html页面
- kibana 对es的简单操作。
一.查询和查看. #1.查询所有的数据 GET _search { "query": { "match_all":{} } } #2. 查看ES集群的健康状态 ...
- Arduino+ESP32 之 驱动GC9A01圆形LCD(二),移植LVGL,跑示例程序,显示自制图片
在前文Arduino+ESP32 之 驱动GC9A01圆形LCD(一), 我们已经移植好了arduino GFX库, 该库的示例程序内,还有LVGL的示例程序哦. arduino环境下移植lvgl是很 ...