您的位置:首页 > 运维架构 > Linux

linux 输入参数利用getopt、struct option、getopt_long、getopt_long_only解析

2018-02-08 13:50 886 查看

Linux 函数处理选项和参数

1、struct option 结构体struct option {
const char *name;
int has_arg;
int *flag;
int val;
};含义如下:
name指明长选项的名称;
has_arg指明该选项是否带参数,1为是,0为否,2为可选;
flag指明长选项如何返回,如果flag为NULL,则getopt_long返回val;否则返回0,flag指向的值赋值为val变量的值。如果该长选项没有发现,flag指向的值保持不变;val指明返回的值,或者需要加载到被flag所指示的变量中的值。option数组的最后一个元素必须全部填充0.
2、关于长选项和短选项
GNU/Linux的命令行选项有两种类型:短选项和长选项,前者以 '-' 作为前导符,后者以 '--' 作为前导符
例如:
process -a w --add -b --file a.txt b.txt - -- -e c.txt
含义如下:
a是短选项,带一个参数vv;
add是长选项,无参数;
b是短选项,无参数;
file是长选项,带一个参数a.txt;
b.txt是参数;
-是参数,通常表示标准输入,stdin; 
--是一个指示符,表明停止扫描参数,其后所有部分都是参数,而不是选项;
-e是参数;
c.txt是参数
3、选项分析函数 #include <unistd.h>
int getopt(int argc, char * const argv[],const char *optstring);
全局变量:
extern char *optarg;
extern int optind, opterr, optopt;

#define _GNU_SOURCE
#include <getopt.h>
int getopt_long(int argc, char * const argv[],const char *optstring,const struct option *longopts, int *longindex);
int getopt_long_only(int argc, char * const argv[],const char *optstring,const struct option *longopts, int *longindex);
4、选项分析函数解析1)getopt()函数,分析短选项参数含义如下:argc, argv是从main函数获取的参数,原样传给getopt;argc记录参数个数,包括函数名;argv存储函数参数,包括函数名;
optstring为字符串,指示如何分析参数。关于optstring的几点说明:
a、如果选项带参数,该选项后接冒号,比如上例中optstring为"a:b",指示a带参数,b没有参数;
b、如果选项带可选参数,该选项后接两个冒号,比如"a::b",表明a可能有参数,也可能没有;
c、如果optstring的开头字符为':',表明如果指明选项带参数,而实际命令行没有参数时,getopt返回':'而不是'?'(默认情况下返回'?',和无法识别选项时返回一样);
d、如果optstring的开头字符为'+',表明一但遇到一个无选项的参数(指参数前面没有选项),马上停止扫描,随后的部分当作参数来解释;
e、如果optstring的开头字符为'-',表明如果遇到无选项的参数,则把它当作选项1(不是字符'1')的参数(不是很明白)f、该函数每解析完一个选项,就返回该选项字符。g、如果选项带参数,参数保存在optarg中。如果选项带可选参数,而实际无参数时,optarg为NULL。h、当遇到一个不在optstring指明的选项时,返回字符‘?’;如果在optstring指明某选项带参数而实际没有参数时,返回字符‘?’或者字符‘:’,视optstring的第一个字符而定。这两种情况选项的实际值被保存在optopt中。i、当解析错误时,如果opterr为1则自动打印一条错误消息(默认),否则不打印。j、当解析完成时,返回-1。k、每当解析完一个argv,optind就会递增。如果遇到无选项的参数,getopt默认会把该参数调后一位(本人理解应该是指针位置往后串),接着解析下一个参数(这里的参数包括:选项、选项所带的参数、无选项的参数,是个广义的参数概念)。如果解析完成后还有无选项的参数,则optind指示的是第一个无选项的参数在argv中的索引。2)getopt_long()函数,同时可以分析短选项和长选项getopt_long的最后一个参数longindex在函数返回时指向被搜索到的选项在longopts数组中的下标。longindex可以为NULL,表明不需要返回这个值。例子:static const struct option lopts[] = {{ "rtc", 1, 0, 'T'},
{ "rs485", 1, 0, '5'},
{ "spiw", 1, 0, 'S'},
{"capture", 1, 0, 'F'},
{"play", 1, 0, 'P'},
{"ipaddr", 1, 0, 'A'},
{ NULL, 0, 0, 0 }}; //第三个成员最好填NULL,不填0int c;
while(1){c = getopt_long(argc, argv, "A:T:5:F:P:S", lopts, NULL);if (c == -1)
break;switch(c){参数保存在optarg中。。。}}
3)get_long_only()函数getopt_long_only类似于getopt_long,但是它把'-'开头的选项当作长选项来处理,一般情况下,这时结构体数组变量longopts中也会包含我们想分析的短选项。如果该选项与长选项不匹配,而与短选项匹配,则可以作为短选项解析。在短选项找到的时候,getopt_long和getopt_long_only的表现和getopt一样。如果长选项找到了,如果flag为 NULL,返回val,否则返回0。错误情况的处理和getopt一样,只是返回'?'时还可能是别的情况引起的:选项含糊不明确或者无关参数。

Comments SHELL编程如何解析命令行参数

问题描述:在linux shell中如何处理tail -n 10 access.log这样的命令行选项?
在bash中,可以用以下三种方式来处理命令行参数,每种方式都有自己的应用场景。
1,直接处理,依次对$1,$2,...,$n进行解析,分别手工处理;
2,getopts来处理,单个字符选项的情况(如:-n 10 -f file.txt等选项);
3,getopt,可以处理单个字符选项,也可以处理长选项long-option(如:--prefix=/home等)。
总结:小脚本手工处理即可,getopts能处理绝大多数的情况,getopt较复杂、功能也更强大。
1,直接手工处理位置参数
必须要要知道几个变量,

复制代码代码如下:
   *    $0 :即命令本身,相当于c/c++中的argv[0]
    *    $1 :第一个参数.
    *    $2, $3, $4 ... :第2、3、4个参数,依次类推。
    *    $#  参数的个数,不包括命令本身
    *    $@ :参数本身的列表,也不包括命令本身
    *    $* :和$@相同,但"$*" 和 "$@"(加引号)并不同,"$*"将所有的参数解释成一个字符串,而"$@"是一个参数数组。

手工处理方式能满足多数的简单需求,配合shift使用也能构造出强大的功能,但处理复杂选项时建议用下面的两种方法。
例子,(getargs.sh):

复制代码代码如下:
#!/bin/bash
if [ $# -lt 1 ]; then
    echo "error.. need args"
    exit 1
fi
echo "commond is $0"
echo "args are:"
for arg in "$@"
do
    echo $arg
done

运行命令:

复制代码代码如下:
./getargs.sh 11 22 cc
commond is ./getargs.sh
args are:
11
22
cc
2,getopts (shell内置命令)
处理命令行参数是一个相似而又复杂的事情,为此,c提供了getopt/getopt_long等函数,c++的boost提供了options库,在shell中,处理此事的是getopts和getopt。
getopts/getopt的区别,getopt是个外部binary文件,而getopts是shell builtin。

复制代码代码如下:
[root@jbxue ~]$ type getopt
getopt is /usr/bin/getopt
[root@jbxue ~]$ type getopts
getopts is a shell builtin
getopts不能直接处理长的选项(如:--prefix=/home等)
关于getopts的使用方法,可以man bash  搜索getopts
getopts有两个参数,第一个参数是一个字符串,包括字符和“:”,每一个字符都是一个有效的选项,如果字符后面带有“:”,表示这个字符有自己的参数。getopts从命令中获取这些参数,并且删去了“-”,并将其赋值在第二个参数中,如果带有自己参数,这个参数赋值在“optarg”中。提供getopts的shell内置了optarg这个变变,getopts修改了这个变量。
这里变量$optarg存储相应选项的参数,而$optind总是存储原始$*中下一个要处理的元素位置。
while getopts ":a:bc" opt  #第一个冒号表示忽略错误;字符后面的冒号表示该选项必须有自己的参数
例子,(getopts.sh):

复制代码代码如下:
echo $*
while getopts ":a:bc" opt
do
        case $opt in
                a ) echo $optarg
                    echo $optind;;
                b ) echo "b $optind";;
                c ) echo "c $optind";;
                ? ) echo "error"
                    exit 1;;
        esac
done
echo $optind
shift $(($optind - 1))
#通过shift $(($optind - 1))的处理,$*中就只保留了除去选项内容的参数,可以在其后进行正常的shell编程处理了。
echo $0
echo $*

执行命令:

复制代码代码如下:
./getopts.sh -a 11 -b -c
-a 11 -b -c
11
3
b 4
c 5
5
./getopts.sh
3,getopt(一个外部工具)
具体用用法可以 man getopt
#-o表示短选项,两个冒号表示该选项有一个可选参数,可选参数必须紧贴选项,如-carg 而不能是-c arg
#--long表示长选项
例子,(getopt.sh):

复制代码代码如下:
#!/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
运行命令:
复制代码代码如下:
./getopt.sh --b-long abc -a -c33 remain
option b, argument `abc'
option a
option c, argument `33'
remaining arguments:
--> `remain'

4.用命令getopts,提供以下代码片段供参考:#!/bin/shwhile getopts xyz: arguments 2>/dev/null
do
case $arguments in
x) echo "option x";;
y) echo "option y";;
z) echo "option z with arg. $OPTARG";;
/?) echo "Usage: optdemo [-xy] [-z argment]"
exit 1;;
esac
doneecho "/$OPTIND is $OPTIND /$OPTERR is $OPTERR"
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  解析输入选项