shell command-line arguments (the getopt and the getopts)

There is also the one, which is part of the foundation:
https://blog.51cto.com/steed/2443313

getopt command

Use getopt command, you can parse any command-line options and parameters, but usage is more complicated. getopt command usage is as follows:

$ getopt --help

用法:
 getopt optstring parameters
 getopt [options] [--] optstring parameters
 getopt [options] -o|--options optstring [options] [--] parameters

选项:
 -a, --alternative            允许长选项以 - 开始
 -h, --help                   这个简短的用法指南
 -l, --longoptions <长选项>  要识别的长选项
 -n, --name <程序名>         将错误报告给的程序名
 -o, --options <选项字符串>  要识别的短选项
 -q, --quiet                  禁止 getopt(3) 的错误报告
 -Q, --quiet-output           无正常输出
 -s, --shell <shell>          设置 shell 引用规则
 -T, --test                   测试 getopt(1) 版本
 -u, --unquoted               不引用输出
 -V, --version                输出版本信息

$ 

Usage There are three formats, the following will be used.

Simply use the command line

Look at the first and most simple format:

 getopt optstring parameters

The first part is the command name.
The second part optstring (string option), this command is parsed format.
The third part of the parameters (parameters getopt command), is the need to parse content.
Therefore, getopt will follow optstring settings, the parameters resolve to the corresponding options and parameters. Reference Example understood:

$ getopt ab:cd -ad value1 -b best1 value2 value3
 -a -d -b best1 -- value1 value2 value3
$ 

The main understand ab:cdthe meaning of.
Here are short definitions of options, there are four letters on behalf of four options. b after the colon indicates that this option requires an argument. B option if you do not give a parameter, the error will be:

$ getopt ab:cd -ad value1 -b
getopt:选项需要一个参数 -- b
 -a -d -- value1
$ 

Use double-dashed line
if you add a double dashed line, then what is behind without wheels, rather than as an argument will be options to deal with:

$ getopt ab:cd -- -ad value1 -b best1 value2 value3
 -- -ad value1 -b best1 value2 value3
$ getopt ab:cd -ad value1 -- -b best1 value2 value3
 -a -d -- value1 -b best1 value2 value3
$ 

This is still the first format command usage, double broken line is part of the parameters of the content.
Content before double-dashed line position in accordance with optstring appears set to resolve, after all considered to be content parameters. Even if there are similar options, to be recognized as a parameter.

Parameters of the problem space comprising
a first and a second format, the third is a difference in functionality. Here the output parameters are not quoted. While the other two formats output parameters are quoted.
Important difference is not on the quotes, but this usage parameter handling spaces and quotes are not supported. It will spaces as parameter separator, rather than a double quotation marks them as parameters.

Support long options

Referring to the example above, plus support for long options. Examples of using long options are as follows:

$ getopt -o ab:cd --long arga,argb:,argc,argd -- -ad -b best --argd value1 value2
 -a -d -b 'best' --argd -- 'value1' 'value2'
$ 

This is the third format command usage.
-o option means that the definition of short
--long actually --longoptions, but omitted any program can recognize letters. Or you can use -l. This is the designated long options. All content should be put together, no spaces. Separated by commas options. After defining, with double dashes separated, behind the content is parameters.

The report cites the wrong program name

It has been tried once before parsing errors reported:

$ getopt ab:cd -ad value1 -b
getopt:选项需要一个参数 -- b
 -a -d -- value1
$ 

Here is getopt error reporting error, it can replace the default content. Usually the name of the script into execution.
As used herein command usage of the second form, the optstring and parameters are put back-breaking double polyline:

$ getopt -- ab:cd -ad value1 -b best1
 -a -d -b 'best1' -- 'value1'
$ 

In this double-dashed line in front of the options you can add getopt command here to specify the -n option:

$ getopt -n test.sh -- ab:cd -ad value1 -b 
test.sh:选项需要一个参数 -- b
 -a -d -- 'value1'
$ 

Here to see the parcel error that name has been replaced.
In the script, you can use $(basename $0)or directly \ $ 0.

Prohibition error reporting
and a -q parameter can disable error reporting, parsing errors options and parameters will be discarded:

$ getopt -n test.sh -q -- ab:cd -ad value1 -b 
 -a -d -- 'value1'
$ 

Optional parameters

Another optional parameters, use two colons. This option can have one or zero parameters:

$ getopt -o a::bc: -l arga::,argb,argc: -- -a value1 --arga value2
 -a '' --arga '' -- 'value1' 'value2'
$ getopt -o a::bc: -l arga::,argb,argc: -- -avalue1 --arga=value2
 -a 'value1' --arga 'value2' --
$ 

The first execution is passed as a parameter is wrong. Because there is not an optional separated by a space, or there will be ambiguity between the parameters and parameter values. It must be considered to be linked to the previous parameter options. Otherwise, it was recognized as a separate parameter.

summary

getopt Options command specified by the option string of rules:

  • Short options, each character represents an option
  • Long options, each option represents a string, separated by commas
  • Option followed by a colon, an option that requires an argument
  • Option is followed by two colons to indicate the option has an optional argument (one or zero parameters)
  • Optional No spaces, short option to link directly between the parameters and parameter values, long options put together by an equal sign

In the script using getopt

Getopt command can now use the command-line parameters according to a predetermined format resolved into a structured format. And in the resolution process, but also found a malformed parameters and report.
The next step is to use the parameters after getopt parse command in the script.

set command

To use getopt in the script. First of all, we want to use to replace the existing command-line options and parameters getopt command generates a formatted version. You need to use the set command.
process variables can be set command shell. Specifically not expanded, only an option of this command here, a double broken line (-). The effect is to replace the command line parameters to the set command parameter value.
The method then copies the original script command line parameters to the command execution getopt, then after getopt output command transmitted to the set command, the command line parameters getopt to replace the original format of the command line parameters:

set -- $(getopt ab:cd "$@")

The original value of the current command line parameter variables will be replaced getopt output command. The getopt format has been good for our command-line arguments.

Use directly

On the basis of the script written before, just add one line of code at the beginning, you can directly use:

set -- $(getopt a:b:s:u "$@")

After adding the phrase, it is to make the subsequent processing parameters getopt return code, rather than the command of the command line arguments.
Verify the effect of:

$ ./format.sh -u -a after -b befor value1 value2 value3
BEFOR_VALUE1_AFTER
BEFOR_VALUE2_AFTER
BEFOR_VALUE3_AFTER
$ ./format.sh -u -a after -b befor value1 "value2 value3" value4
BEFOR_VALUE1_AFTER
BEFOR_VALUE2_AFTER
BEFOR_VALUE3_AFTER
BEFOR_VALUE4_AFTER
$ 

The second command does not process parameters with spaces, as used herein, it is the first format of getopt.

The second format is to resolve

To deal with space, it is necessary to use the second format (or third), the command will be modified as follows:

set -- $(getopt -- a:b:s:u "$@")

Simple in front with double dashed line just fine. This statement is wrong, but also to modify the back.

Again verify:

$ ./format.sh -u -a after -b befor value1 "value2 value3" value4
'BEFOR'_'VALUE1'_'AFTER'
'BEFOR'_'VALUE2_'AFTER'
'BEFOR'_VALUE3'_'AFTER'
'BEFOR'_'VALUE4'_'AFTER'
$ 

Using a second, third format, will be in quotation marks to define the parameter content. But the quotes interfere with the set command.

Use eval command
here there is a new problem, not only failed to correctly handle spaces, as well as the contents of the output of additional quotes. Problem space to put off, here need to use eval command to solve new problems.

eval command contents subsequent read and executed as a single command, where the command for processing the generated escape character getopt parameter.

About eval command, as well as scenarios for use. Sometimes splicing out the string in the script even print it out to see properly. And directly copy, paste can also be read as a command to run properly interactive interface. But it can not be executed in the script. This time you can use the eval command to resolve. It is able to string as a command to execute.
And determine a complex mosaic of command when the situation can not be implemented and sometimes there will be a variety of references in the script. This time on direct assignment, paste interface to exchange a try, if the result of splicing itself is no problem, then after adding eval command, you should be able to run with.

Modify the command as follows:

eval set -- $(getopt -- a:b:s:u "$@")

Verify again:

$ ./format.sh -u -a after -b befor value1 "value2 value3" value4
BEFOR_VALUE1_AFTER
BEFOR_VALUE2 VALUE3_AFTER
BEFOR_VALUE4_AFTER
$ 

The first format plus eval command is no problem, so you can spend no brain.

To solve the space problem

As long as the correct use of getopt second or third format, then the problem parameters that contain spaces will be solved. A fancy bar.

Parameter parsing error and quits

When the command is executed, using the wrong parameters, the current effect is as follows:

$ ./format.sh -u -w -a after -b befor value1 "value2 value3" value4
getopt:无效选项 -- w
BEFOR_VALUE1_AFTER
BEFOR_VALUE2 VALUE3_AFTER
BEFOR_VALUE4_AFTER
$ 

Resolve the problems found and reported, but the script is not terminated, but continues to perform. To determine if a parse error, you need to use \ $? Parameter. Then exit the script is to use the exit command.
Here direct direct use \ $? And you can not get to the parameter parsing error results. Because the result this time was set command (may be eval command) the results of which are then getopt before a command.
Solve this problem, we first getopt command again, to judge. Then again set to call again, you can use the results of previously performed directly:

getopt_cmd=$(getopt -n $(basename $0) -- a:b:s:u "$@")
[ $? -ne 0 ] && exit 1
eval set -- "$getopt_cmd"

There is also coupled with a defined name when reporting errors. Also specify a non-zero exit status exit to exit, because it is a runtime error.

Verify the effect of:

$ ./format.sh -v -a after -w -b
format.sh:无效选项 -- v
format.sh:无效选项 -- w
format.sh:选项需要一个参数 -- b
$ echo $?
1
$ 

After the resolution problem now, it will exit.

Complete code sample

Here plus feature length options and optional parameters.
It added an extra parameter -m, --markdue specify what connectors:

  • Default directly connected, without using a hyphen
  • Plus the option to use the default underscore
  • After the option to add parameters, use the parameter to connect

More parameters, plus the -h, --helpoption to print parameter description.

The complete code is as follows:

$ cat format.sh
#!/bin/bash
mark=""      # 连接符号
prefix=""    # 前缀
base="test"  # 默认字符串
suffix=""    # 后缀
upper=off    # 是否大写
# 显示声明一下这是个数组变量,其实没有必要
declare -a names  # 需要格式化输出的所有原始字符串
# 打印的帮助信息
help_str="
参数说明:
  -h, --help:           打印帮助信息
  -m, --mark [连接符]:  使用连接符,默认是下划线(_),可以指定
  -a, --after string:   添加后缀
  -b, --befor string:   添加前缀
  -s, --string string:  指定中间的字符串,默认是“test”
  -u, --upper:          全大写输出
"
# 解析命令行参数
getopt_cmd=$(getopt -o m::ha:b:s:u --long mark::,help,after:,befor:,string:,upper -n $(basename $0) -- "$@")
[ $? -ne 0 ] && exit 1
eval set -- "$getopt_cmd"
# 解析选项
while [ -n "$1" ]
do
    case "$1" in
        -m|--mark)
            case "$2" in
                "")
                    mark="_"
                    shift ;;
                *)
                    mark="$2"
                    shift ;;
            esac
            ;;
        -h|--help)
            echo -e "$help_str"
            exit ;;
        -a|--after)
            suffix="$2"
            shift ;;
        -b|--befor)
            prefix="$2"
            shift ;;
        -s|--string)
            base="$2"
            shift ;;
        -u|--upper)
            upper=on ;;
        --) shift
            break ;;
         *) echo "$1 is not an option"
            exit 1 ;;  # 发现未知参数,直接退出
    esac
    shift
done
# 解析参数
while [ -n "$1" ]
do
    names=("${names[@]}" "$1")
    shift
done
names[0]=${names[0]:-$base}
for name in "${names[@]}"
do
    # 添加前缀和后缀
    output="${prefix:+${prefix}${mark}}${name}${suffix:+${mark}${suffix}}"
    # 判断是否要全大写输出
    if [ $upper = on ]
    then
        output=${output^^}
    fi
    # 输出结果
    echo "$output"
done
$ 

Verify the effect of:

$ ./format.sh -a after -b befor VALUE1 "VALUE2 VALUE3" VALUE4
beforVALUE1after
beforVALUE2 VALUE3after
beforVALUE4after
$ ./format.sh -a after -b befor --mark 
befor_test_after
$ ./format.sh -a after -b befor --mark="||" -u
BEFOR||TEST||AFTER
$ ./format.sh -a after -b befor --mark="||" -u --help

参数说明:
  -h, --help:           打印帮助信息
  -m, --mark [连接符]:  使用连接符,默认是下划线(_),可以指定
  -a, --after string:   添加后缀
  -b, --befor string:   添加前缀
  -s, --string string:  指定中间的字符串,默认是“test”
  -u, --upper:          全大写输出

$ 

There getopt suffice. Simply, the way and then the next getopts.
getopts function on almost, but more advanced package, simpler to use, the code will need less.

getopts command

Another tool is getopts parse command line arguments. It is the Bash internal command.
It has the advantage:

  • Position does not need to be processed by an external program parameters
  • Shell can be easily arranged to parse the variables
  • getopts defined by POSIX

Does not support long options:

Long options (--long) getopts can not resolve GUN style, can not resolve XF86 style long options (-long)

getopt only produces an output after processing options and parameters. We would also like to use set to complete the work delivered.
getopts can and act in harmony existing shell variable parameters. On each call, a process only on a command line parameter detected. After processing, it exits and returns an exit status code greater than 0. This is very convenient to be used in a while loop.

Basic Usage

getopts will be used to look at three variables:
OPTIND: the index of the next argument to be processed is stored. This is getopts remember their state during the call mode.
OPTARG: parameter options by the getopts find the corresponding.
OPTERR: a value of 0 or 1. It indicates whether the Bash should display an error message generated by the getopts.

The basic syntax of the getopts command:

getopts 选项字符串 名称 [参数]

Option string (OPTSTRING): getopts what options there, what are the parameters (a colon after options)
Name (VARNAME): getopts will find the option to assign the variable name
parameter (ARGS): the general lack of Province, getopts will parse all the parameters to the script calls. If this parameter is performed, getopts will not resolve the parameters passed to the script, but rather to resolve parameters here.

getopts will not move variables. After all options have been processed, the command will stop, and left us to continue processing parameters. At this time, with the first value can be used OPTIND shit command to move to the position of the first parameter:

shift $[ $OPTIND - 1 ]

Error reporting mode

getopts command supports two modes bug report:

  • Detailed error reporting mode
  • Error reporting mode suppression

For products in the script, it is recommended to suppress error reporting mode.

Detailed error reporting mode
in the detailed error reporting mode, if getopts encounters an invalid option value VARNAME will be set to the question mark (?), And the variable OPTARG not be set. If you did not find the required parameters, values VARNAME will also be set to a question mark (?), Variable OPRARG will not be set, and will print an error message.

Error reporting mode suppression
in the suppression error reporting mode, if getopts encounters an invalid option value VARNAME will be set to the question mark (?), And the variable OPTARG will be set to the option character. If you did not find the required parameters, VARNAME value will be set to a colon (:), and the variable OPTARG will be included in the option character.
To suppress error reporting mode, only when you call getopts, set to begin with a colon option string (OPTSTRING). The following example is the use of error has been reporting mode.

Sample Code

As used herein suppress error reporting mode, it needs its own analysis and reports parsing errors. In the code:

$ cat say_hello.sh 
#!/bin/bash
defaultname="nobody"  # 默认的名字
declare -a names      # 存放名字的数组
hello="hello"         # 打招呼的用语
end="!"               # 结束的内容
tittle=off            # 是否首字母大写
# 解析选项
while getopts :n:h:e:t opt
do
    case "$opt" in
        n) defaultname="$OPTARG" ;;
        h) hello="$OPTARG" ;;
        e) end="$OPTARG" ;;
        t) tittle=on ;;
        :)  # 没有为需要参数的选项指定参数
            echo "This option -$OPTARG requires an argument."
            exit 1 ;;
        ?) # 发现了无效的选项
            echo "-$OPTARG is not an option"
            exit 2 ;;
    esac
done
# 解析参数
shift $[ $OPTIND -1 ]  # 移动到第一个参数的位置
# 这次用for循环遍历
for arg in "$@"
do
    names=("${names[@]}" "$arg")
done
names[0]=${names[0]:-$defaultname}
for name in "${names[@]}"
do
    [ "$tittle" = on ] && output="${hello^} ${name^} $end" || output="$hello $name $end"
    echo "${output}"
done
$ 

Verify performed as follows:

$ ./say_hello.sh 
hello nobody !
$ ./say_hello.sh -n adam
hello adam !
$ ./say_hello.sh -n adam -h hi -e. -t
Hi Adam .
$ ./say_hello.sh -h hi -e. -t adam bob clark
Hi Adam .
Hi Bob .
Hi Clark .
$ ./say_hello.sh -a -h hi -e. -t adam bob clark
-a is not an option
$ ./say_hello.sh -h
This option -h requires an argument.
$ 

Options and parameters can not be mixed up:

$ ./say_hello.sh adam
hello adam !
$ ./say_hello.sh adam -t
hello adam !
hello -t !
$ 

Support for dual-dashed line:

$ ./say_hello.sh -t adam
Hello Adam !
$ ./say_hello.sh -t -- adam
Hello Adam !
$ 

More down, a lot easier to use than the getopt, but also a lot of difference on the function, optional parameters (double colon: :) should also not supported. In addition, if familiar with getopt then, every step of the operations are controlled by their own code. The getopts simplifies many places, such as mobile shift is not called variables.

The standardized options

Some letter options have a certain level of standard meaning in the Linux world. If you support these options in the shell script, you should use the standard letters to define.
Here are some command line options are often used options and meanings:
Options description
-a Show all objects (show hide)
-c Generating a count
-d Specify a directory
-e Extension of an object
-f Specifies the read data file
-h Displays help information about the command
-i Ignore text case
-l Produce long format output version
-n Use non-interactive mode (batch)
-The Redirect all output to the specified output file
-q Run in quiet mode
-r Recursively processing directories and files
-s Run in quiet mode
-v Generates detailed output
-x Exclude an object
-Y Answer yes to all questions

Guess you like

Origin blog.51cto.com/steed/2443718