在编写shell程序时经常需要处理命令行参数,本文描述在bash下的命令行处理方式。
选项与参数:
如下命令行:

./test.sh -f config.conf -v --prefix=/home

-f为选项,它需要一个参数,即config.conf, -v 也是一个选项,但它不需要参数。
--prefix我们称之为一个长选项,即选项本身多于一个字符,它也需要一个参数,用等号连接,当然等号不是必须的,/home可以直接写在--prefix后面,即--prefix/home,更多的限制后面具体会讲到。
在bash中,可以用以下三种方式来处理命令行参数,每种方式都有自己的应用场景。
* 手工处理方式
* getopts
* getopt
依次讨论这三种处理方式。
1.手工处理方式
在手工处理方式中,首先要知道几个变量,还是以上面的命令行为例:

*    $ : ./test.sh,即命令本身,相当于c/c++中的argv[]
* $ : -f,第一个参数.
* $ : config.conf
* $, $ ... :类推。
* $# 参数的个数,不包括命令本身,上例中$#为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 会打印:
-f config.conf -n 10    #这是"$*"的输出
-f   #以下为$@的输出
config.conf
-n
10
所以,手工处理的方式即对这些变量的处理。因为手工处理高度依赖于你在命令行上所传参数的位置,所以一般都只用来处理较简单的参数。
(脚本学堂 www.jb51.net 编辑整理)
例如:
./test.sh 10
而很少使用./test -n 10这种带选项的方式。 典型用法为:

#!/bin/bash
if [ x$ != x ]
then
#...有参数
else
then
#...没有参数
fi

为什么要使用 x$1 != x 这种方式来比较呢?想像一下这种方式比较:
if [ -n $1 ]  #$1不为空
但如果用户不传参数的时候,$1为空,这时 就会变成 [ -n ] ,所以需要加一个辅助字符串来进行比较。
手工处理方式能满足大多数的简单需求,配合shift使用也能构造出强大的功能,但在要处理复杂选项的时候建议用下面的两种方法。

2. 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 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() program.
# this program will only work with bash()
# an similar program using the tcsh() 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 [ $? != ] ; then echo "terminating..." >& ; exit ; fi
# note the quotes around `$temp': they are essential!
#set 会重新排列参数的顺序,也就是改变$,$...$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 ;;
-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 ;;
*) echo "option c, argument \`$2'" ; shift ;;
esac ;;
--) shift ; break ;;
*) echo "internal error!" ; exit ;;
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,$2指向-b,$3指向arg,$4指向-c,$5指向--,而多出的arg1则被放到了最后。
3,总结
一般小脚本手工处理也就够了,getopts能处理绝大多数的情况,getopt较复杂,功能也更强大。

bash shell命令行选项与修传入参数处理的更多相关文章

  1. getopt:命令行选项、参数处理

    在写shell脚本时经常会用到命令行选项.参数处理方式,如: ./test.sh -f config.conf -v --prefix=/home -f 为短选项,它需要一个参数,即config.co ...

  2. 命令行选项解析函数(C语言):getopt()和getopt_long()

    命令行选项解析函数(C语言):getopt()和getopt_long() 上午在看源码项目webbench时,刚开始就被一个似乎挺陌生函数getopt_long()给卡住了,说实话这函数没怎么见过, ...

  3. 命令行选项 - Mozilla 产品与私有技术 | MDN - Google Chrome

    命令行选项 在本文章中 语法规则 使用命令行选项 示例 用户配置档 -CreateProfile profile_name -CreateProfile "profile_name prof ...

  4. Kafka Broker | 命令行选项和过程

    1.目标 在这个Apache Kafka教程中,我们将学习Kafka Broker.Kafka Broker管理主题中的消息存储.如果Apache Kafka有多个代理,那就是我们所说的Kafka集群 ...

  5. NUnit-Console 命令行选项详解

    本文为 Dennis Gao 原创或翻译技术文章,发表于博客园博客,未经作者本人允许禁止任何形式的转载. NUnit-Console 命令行选项 NUnit-Console 命令行选项列表 指定运行哪 ...

  6. bash shell命令(2)

    在上篇<bash shell命令(1)>中,介绍了几种简单的linux shell命令,今天继续介绍bash shell命令 本文地址:http://www.cnblogs.com/arc ...

  7. python argparse模块解析命令行选项简单使用

    argparse模块的解析命令行选项简单使用 util.py #!/usr/bin/env python # coding=utf-8 import argparse parser = argpars ...

  8. ipython, 一个 python 的交互式 shell,比默认的python shell 好用得多,支持变量自动补全,自动缩进,支持 bash shell 命令,内置了许多很有用的功能和函数

    一个 python 的交互式 shell,比默认的python shell 好用得多,支持变量自动补全,自动缩进,支持 bash shell 命令,内置了许多很有用的功能和函数. 若用的是fish s ...

  9. 第四章:更多的bash shell命令

    第四章:更多的bash shell命令 监测程序 ps (其他ps内容见#1 ) Unix风格的ps命令参数 参数 描述 -A 显示所有进程 -N 显示与指定参数不符的所有进程 -a 显示除控制进程( ...

随机推荐

  1. 使用asp.net从零开始制作设计网站---转载

    首先感谢提供此教程的朋友,可以给大家学习的机会,很有用,留着好好学.如下正文: 1. 申请域名 2. 购买空间 3. 备案 4. 使用photoshop完成设计与切图  5. 使用dreamweave ...

  2. Android种 adb是什么(转)

    提到adb.exe,一直关注我们Android系列教程的朋友们应该不会感到陌生,因为无论取得 Root权限或者刷机的时候我们都通过adb直接操作管理Android手机,但是可能大多数对于adb仅仅局限 ...

  3. MVC的处理过程

    MVC的处理过程,首先控制器接受用户的请求,并决定应该调用哪个模型来进行处理,然后模型用业务逻辑来处理用户的请求并返回数据,最后控制器用相应的视图格式化模型返回的数据,并通过表示层呈现给用户.

  4. Android图形基础

    Android图形基础 Android在其android.graphics包中提供了完整的本机二维图像库. Color类,代表颜色,是用4个数字表示的,透明度.红色.绿色和蓝色(Alpha.Red.G ...

  5. 【JSP jstl c标签】使用c:foreach 报错(警告)”test does not support runtime expressions“

    后台封装的数据是个list,传递给前台,显示如下: <c:forEach items="${userInfo}" var="user"> 用户Nam ...

  6. jmeter性能测试实战-web登录测试

    一.项目背景: 网站信息: 操作系统类型 二.需求: 登录并发测试 三.场景: 1s增加两个线程,运行2000次 分别看20.40.60并发下的表现 四.监控: 成功率.响应时间.标准差.cpu.me ...

  7. Java的锁优化

    高效并发是从JDK 1.5到JDK 1.6的一个重要改进,HotSpot虚拟机开发团队在这个版本上花费了大量的精力去实现各种锁优化技术,如适应性自旋(Adaptive Spinning).锁消除(Lo ...

  8. 2016.6.17 计算机网络复习要点之PPP协议

    点对点协议PPP是目前使用最广泛的数据链路层协议. 1.PPP协议的特点: **我们知道因特网用户通常需要连接到某个ISP才能接入到因特网,PPP协议就是用计算机和ISP进行通信时所使用的数据链路层协 ...

  9. DelPhi连接数据库方式

    一.SQL Server 2000 的连接数据库 1.无密码连接SQLL:='Provider=SQLOLEDB.1;Persist Security Info=False;User ID=sa;In ...

  10. Jexus & Mono 迁移

     具体案例: 问:  这个是现在微信公共平台的进三月请求数合计 如果迁移到 Mono & Jexus 需要注意那些?  因为微信需要的是5秒响应,服务号存在时段高峰值,在峰值上,一台服务器能否 ...