如何在 Bash 中使用 getopt 和长选项?

Posted

技术标签:

【中文标题】如何在 Bash 中使用 getopt 和长选项?【英文标题】:How to use getopt with long options in Bash? 【发布时间】:2017-05-29 19:46:46 【问题描述】:

我在 Bash 中有以下代码:

declare BPM_USERNAME,BPM_PASSWORD,HOST,TARGET_IP,OVERRIDE_STATUS=''
OPTS=`getopt -a --longoptions username:,password:,csc:,ip:,override: -n "$0" -- "$@"`
eval set -- "$OPTS"

if [ $? != 0 ] ; then echo "Failed parsing options." >&2 ; exit 1 ; fi

while true; do
    echo ""
    echo $OPTS
    echo $1
    echo $2

  case "$1" in
    --username )
        BPM_USERNAME=$2
        shift 2
        ;;
    --password )
        BPM_PASSWORD=$2
        shift 2
        ;;
    --csc )
        HOST=$2
        shift 2
        ;;
    --ip )
        TARGET_IP=$2
        shift 2
        ;;
    --override )
        OVERRIDE_STATUS=$2
        shift 2
        ;;
    --)
        shift
        echo "Breaking While loop"
        break
        ;;
    *)
        echo ""
        echo "Error in given Parameters. Undefined: "
        echo $*
        echo ""
        echo "Usage: $0 [--username BPM_USERNAME] [--password BPM_PASSWORD] [--ip IP ADDRESS_OF_VyOS/BPM] [--csc CLIENT_SHORT_CODE] [--override TRUE/FALSE]"
        exit 1
  esac
done

我向 Bash 发出以下命令(脚本名称为 UpdateSSL.sh):

./UpdateSSL.sh -username bpmadmin -password bpmadmin -ip 10.91.201.99 -csc xyz -override False

但我没有解析选项,而是返回以下结果(表明 while 循环转到 *) 案例):

'bpmadmin' --password 'bpmadmin' --ip '10.91.201.99' --csc 'xyz' --override 'False' --
bpmadmin
--password

Error in given Parameters. Undefined: 
bpmadmin --password bpmadmin --ip 10.91.201.99 --csc xyz --override False --

Usage: ./UpdateSSL.sh [--username BPM_USERNAME] [--password BPM_PASSWORD] [--ip IP ADDRESS_OF_VyOS/BPM] [--csc CLIENT_SHORT_CODE] [--override TRUE/FALSE]

我不知道我做错了什么。

【问题讨论】:

eval 是不必要的; set -- $OPTS(没有引号)就足够了。 做到了。仍然是 while 循环转到 *) 案例。 【参考方案1】:

答案其实在man page的最后:

如果您根本不想要任何短选项变量的语法不是很直观(您必须将它们显式设置为空字符串)。

为了使getopt 在没有短选项的情况下运行,您必须手动指定-o '' 作为第一个参数。我进行了一些其他更改,以下内容适用于我的系统(请参阅*** 标记):

#!/bin/bash

# *** Make sure you have a new enough getopt to handle long options (see the man page)
getopt -T &>/dev/null
if [[ $? -ne 4 ]]; then echo "Getopt is too old!" >&2 ; exit 1 ; fi

declare BPM_USERNAME,BPM_PASSWORD,HOST,TARGET_IP,OVERRIDE_STATUS=''
OPTS=$(getopt -o '' -a --longoptions 'username:,password:,csc:,ip:,override:' -n "$0" -- "$@")
    # *** Added -o '' ; surrounted the longoptions by ''
if [[ $? -ne 0 ]] ; then echo "Failed parsing options." >&2 ; exit 1 ; fi
    # *** This has to be right after the OPTS= assignment or $? will be overwritten

set -- $OPTS
    # *** As suggested by chepner

while true; do
    # ... no changes in the while loop
done

【讨论】:

@AhmadShah 你有机会尝试一下吗? 尝试将 set -- $OPTS 更改为 eval set -- "$OPTS" ...此代码示例替代方案可以更好地处理包含空格的参数“$@”。

以上是关于如何在 Bash 中使用 getopt 和长选项?的主要内容,如果未能解决你的问题,请参考以下文章

使用getopt命令解析shell脚本的命令行选项

sh 如何使用bash / getopt解析选项的示例

如何使用内置 Bash getopts 的长选项?

使用 getopts (bash) 的多个选项参数

Python中getopt()函数的使用

Python中getopt()函数的使用