• 【Linux 】向Shell脚本传递参数、getopts、getopt



    【Linux 】getopts 可选参数_Bash技巧:介绍 getopts 内置命令解析选项参数的用法

    1. 概述

    命令行传递给Shell脚本的参数又称为位置参数,这是因为Shell脚本会根据参数的位置来接收它们的值。在Shell脚本内部,用户可以通过一系列的系统变量来获取参数,这些系统变量的名称是固定的,并且简单。如下表所列:

    常用的系统参数
    变量名说明
    $n表示传递给脚本的第n个参数,例如$1表示传递的第一个参数,$2表示第二个参数,以此类推
    $#传入的参数个数
    $0当前脚本名称
    $*以“参数1 参数2 ...”的形式返回所有参数的值
    $@以"参数1" “参数2”...的形式返回所有参数的值
    $_最后一个参数

    注意:

    • 由单引号或者双引号引起来的字符串作为一个参数进行传递,传递时会去掉引号
    • 对于包含空格字符或者其他特殊符号的参数,需要使用单引号或者双引号进行传递,避免被误解析。如果参数中有空格或者其他特殊字符,就不能使用 ∗ 来获取所有参数了,而要使用 *来获取所有参数了,而要使用 来获取所有参数了,而要使用@。
    • $#返回的参数个数,不包括$0.
    • 如果用户传递的参数大于9个,不能使用$10表示第10个参数。为了获取第10个参数,用户碧玺先处理或者保存$1,然后使用shift命令删除参数1并将所有剩余的参数下移1位,此时第10个参数就变成了 9 ,以此类推。 9,以此类推。 9,以此类推。#的值将被更新以反映参数的剩余数量。这样代码上就比较好迭代处理。

    编写如下脚本:

    #!/bin/bash
    echo "$# paramters num"
    echo "$@"
    echo "$*"
    echo $@
    echo $*
    echo $_
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    执行如下命令以及结果:

    eden_ubuntu@edenubuntu:~/Documents/Shell$ ./1-3.sh a "b c" d 111
    4 paramters num
    a b c d 111
    a b c d 111
    a b c d 111
    a b c d 111
    111
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    2. 参数扩展

    对于简单的情况,上述系统变量以及足够。但是在实践中,用户遇到的并不总是这种简单的情况。例如我们经常使用的ls命令,我们可以输入

    ls -l
    ls -la
    ls -lrt
    
    • 1
    • 2
    • 3

    等等不同的参数来执行不同的操作,这样单纯的使用$1,$2…已经不能满足要求了,这个时候我们需要使用参数扩展,Shell程序中使用getopts命令,接下来我们详细说说如何使用它。

    2.1 getopts

    注意:getopts 是 bash 的内置命令。对于 bash 内置命令来说,不能用 man 命令查看它们的帮助说明。
    要使用 help 命令查看。 help getopts

    getopts是bash支持的命令,getopts的基本语法如下:

    getopts optstring [arg]
    
    • 1

    optstring是一个字符串,包含一个可以为getopts命令识别的选项名称列表。我们让s表示一个字符,其中语法为:

    选项内容说明
           :optsring如果以:开头,表示是静默模式,忽略一般错误消息
          s有效选项并且后面不带参数值
          s:有效选项并且后面必须带参数值

    getopts会依次遍历每个选项并将选项名称保存到arg中,OPTARG将保存对于选项的参数值。

    我们举例说明:

    #!/bin/bash
     
    #input paramters index
    echo "OPTIND starts at $OPTIND"
    #get paramters
    while getopts ":pq:x::" optname              # while在迭代时,系统语法会检查当前项是否合法
     do                                #当前项合法后,才会进入do 语句
     case "$optname" in                           
            "p")            #p
              echo "Option $optname is specified"
              ;;
            "q")            #q
              echo "Option $optname has value $OPTARG"
              ;;
            "?")             #
              echo "Unknown option $OPTARG"
              ;;
            ":")
              echo "No argument value for option $OPTARG"
              ;;
            *)                 #出现上述枚举项之外的项,会进入该分支
              # Should not occur
              echo "Unknown error while processing options"
              ;;
     esac
     echo "OPTION is now $OPTIND"
    done
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    “:pq:”表示:

    • getopts忽略错误信息;-p后不接参数,-q后接参数

    • OPTIND是系统变量,表示当前getopts索取参数的下标位置

    执行如下命令与结果:

    eden_ubuntu@edenubuntu:~/Documents/Shell$ ./1-4.sh -p -q 12
    OPTIND starts at 1
    Option p is specified
    OPTION is now 2
    Option q has value 12
    OPTION is now 4
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    注意如下命令也能有同样效果:

    eden_ubuntu@edenubuntu:~/Documents/Shell$ ./1-4.sh -pq 12
    OPTIND starts at 1
    Option p is specified
    OPTION is now 1
    Option q has value 12
    OPTION is now 3
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    这说明-p -q 12 和-pq 12都能达到我们的目标。所以选项是可以连用的,就像我们平常使用的ls命令: ls -lrt效果等同于 ls -l -r -t.

    那如果我们想让选项支持wide-format呢,比如使用cmake时有:

    cmake -DCMAKE_TOOLCHAIN_FILE=arm-toolchain.cmake .
    
    • 1

    这种getopts是不支持的!!!我们需要使用另外一个命令getopt

    2.2 getopt

    不同于getopts是bash的内置命令,getopt是一个外部命令,不同通常Linux发行版都会自带

    我们使用type命令就能看出差别

    eden_ubuntu@edenubuntu:~/Documents/Shell$ type getopts
    getopts is a shell builtin
    eden_ubuntu@edenubuntu:~/Documents/Shell$ type getopt
    getopt is hashed (/usr/bin/getopt)
    
    • 1
    • 2
    • 3
    • 4

    getopt使用方式

    # 第一种:无法处理带有空格的参数
    getopt [options] optstring parameters
    
    
    • 1
    • 2
    • 3
    • options:getopt自带的参数定义,用来表示长选项还是短选项
      -o或–options选项后面是可接受的短选项
      -l或–long选项后面是可接受的长选项
    • optstring:自定义选项参数 ,例如 -a -b
      选项后面可以跟 一个冒号(:)、两个冒号、没冒号
    • parameters:参数,即参数值,允许为空

    选项后一个冒号(:)、两个冒号、没冒号的区别

    • 无冒号:执行时,只有选项,不带参数。
    • 一个冒号(:):执行时必须带有参数(必选)。
    • 两个冒号(::):执行时可以选择性带参数,也可以不带(可选)。

    getopt支持短选项和长选项, -o或者--option后接短选项,-l或者--long后接长选项:

    • 短选项格式为 -a -b ,即长度为1的字母
    • 长选项格式为 -name ,即多个字母
    • 如果参数是必选,那么短选项的参数值可以是空格,也可以紧贴选项,-c arg或-carg; 长选项的参数可以是空格,也可以=连接,–clong arg 或clong=arg
    • 如果参数是可选,那么短选项的参数值只可以紧贴选项,-carg;长选项的参数值只可以=连接,-clong=arg
    #!/bin/bash
     
    echo original parameters=[$@]
     
    #-o或--options选项后面是可接受的短选项,如ab:c::,表示可接受的短选项为-a -b -c,
    #其中-a选项不接参数,-b选项后必须接参数,-c选项的参数为可选的
    #-l或--long选项后面是可接受的长选项,用逗号分开,冒号的意义同短选项。
    #-n选项后接选项解析错误时提示的脚本名字
    ARGS=`getopt -o ab:c:: --long along,blong:,clong:: -n "$0" -- "$@"`
    if [ $? != 0 ]; then
        echo "Terminating..."
        exit 1
    fi
     
    echo ARGS=[$ARGS]
    #将规范化后的命令行参数分配至位置参数($1,$2,...)
    eval set -- "${ARGS}"
    echo formatted parameters=[$@]
     
    while true
    do
        case "$1" in
            -a|--along) 
                echo "Option a";
                shift
                ;;
            -b|--blong)
                echo "Option b, value=$2";
                shift 2
                ;;
            -c|--clong)
                case "$2" in
                    "")
                        echo "Option c, no value";
                        shift 1  
                        ;;
                    *)
                        echo "Option c, value=$2";
                        shift 2;
                        ;;
                esac
                ;;
            --)
                shift
                echo "shift"
                break
                ;;
            *)
                echo "Internal error!"
                exit 1
                ;;
        esac
    done
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53

    执行命令与结果:

    eden_ubuntu@edenubuntu:~/Documents/Shell$ ./1-5.sh -a -b 1 --clong=2
    original parameters=[-a -b 1 --clong=2]
    ARGS=[ -a -b '1' --clong '2' -- ]   //clong参数后面的值为 ‘2’
    formatted parameters=[-a -b 1 --clong 2 -- ]
    Option a
    Option b, value=1
    Option c, value=2
    shift
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    如果--clong=2改为 -clong 2,结果如下:

    eden_ubuntu@edenubuntu:~/Documents/Shell$ ./1-5.sh -a -b 1 --clong 2
    original parameters=[-a -b 1 --clong 2 ]
    ARGS=[ -a -b '1' --clong '' -- '2' 'test1' 'test2']      //clong参数后面的值为 ‘’
    formatted parameters=[-a -b 1 --clong -- 2 ]
    Option a
    Option b, value=1
    Option c, no value
    shift
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    参考

    Shell系统学习之向Shell脚本传递参数
    Linux-getopt命令详解

  • 相关阅读:
    支付宝小程序关键词优化:引领数字商业的未来
    24.Ubuntu新磁盘挂载
    基于约束关系的图表设计
    STM32F4X I2C LM75
    学习vue3 五,传送,缓存组件以及过渡和过渡列表
    中秋教师节活动方案打印选择哪个平台打印便宜
    医疗大数据系统
    Redis如何实现多可用区?
    【布局优化】基于帝国企鹅算法求解潮流计算的电力系统总线优化问题附matlab代码
    波卡XCM和Cosmos IBC是一样的原理吗?
  • 原文地址:https://blog.csdn.net/m0_45406092/article/details/133276390