BASH getopt命令返回自己的参数而不是命令行参数

时间:2013-02-27 03:07:10

标签: bash parameters options flags getopt

我正在创建一个BASH脚本并使用BASH getopt命令来解析命令行参数。 getopt不返回命令行中提供的参数,而是返回提供给getopt命令的参数。我不确定会发生什么,因为我的代码工作得很完美,而且看似无处不在,它已经停止正常工作(不,我没有更新任何内容或更改任何代码或环境设置)。我不能使用getopts(使用额外的's'),因为出于某种未知原因,它不会安装在将运行此脚本的计算机上。

尽管脚本提供了零命令行参数,但getopt命令由于某种原因返回我提供的所有参数,减去-o标志,而不是预期的--表示选项结束的值。我的代码如下:

SHORT_OPTS=":hvso:l:d:n:p:t:"
LONG_OPTS="help,version,submit-job,output:,library:,job-dir:"
LONG_OPTS="${LONG_OPTS},num-nodes:,num-procs:,max-time:"
OPTS=$(getopt -o "${SHORT_OPTS}" -l "${LONG_OPTS}" -a -n "${PROG_NAME}" -- "${@}")

# Check for invalid command line options and arguments
if [[ ${?} -ne ${SUCCESS} ]] ; then
    echo -e "${PROG_NAME}: error: Invalid option or argument\n" >&2
    usage ; exit ${FAILURE}
else
    echo "BEFORE $@"
    eval set -- ${OPTS}
    echo "AFTER $@"
fi

# Process command line options and their arguments
while true ; do
    case "${1}" in
        -h | --help) 
            # Display script usage information and exit
            usage ; exit ${SUCCESS} ;;
        -v | --version) 
            # Display script version information and exit
            echo "${PROG_NAME} v${PROG_VERSION}" ; exit ${SUCCESS} ;;
        -s | --submit-job) 
            # Enable automatic submission of the Moab job
            JOB_AUTO_SUBMIT="${PREF_YES}" ; shift 1 ;;
        -o | --output) 
            # Set the base name for output file names
            TARGET="${2}" ; shift 2 ;;
        -l | --library) 
            # Set the library to use for NWChem atomic configurations
            NW_LIB="${2}" ; shift 2 ;;
        -d | --job-dir) 
            # Ensure the specified directory for the Moab job exists
            if [[ -e "${2}" ]] ; then
                JOB_WORK_DIR=$(resolvePath "${2}") ; shift 2
            else
                echo -e "${PROG_NAME}: error: -d ${2}: No such directory\n"
                usage ; exit ${FAILURE}
            fi ;;
        -n | --num-nodes) 
            # Ensure the number of compute nodes is greater than zero
            if positiveInt "${2}" ; then
                JOB_NODES="${2}" ; shift 2
            else
                echo -n "${PROG_NAME}: error: -n ${1}: Number of "
                echo -e "job nodes must be a positive integer\n"
                usage ; exit ${FAILURE}
            fi ;;
        -p | --num-procs) 
            # Ensure the number of processors per node is greater than zero
            if positiveInt "${2}" ; then
                JOB_PROCS="${2}" ; shift 2
            else
                echo -n "${PROG_NAME}: error: -p ${2}: Number of "
                echo -e "processors per node must be a positive integer\n"
                usage ; exit ${FAILURE}
            fi ;;
        -t | --max-time) 
            # Ensure the maximum job runtime is in the correct format
            if [[ "${2}" == [0-9][0-9]:[0-9][0-9]:[0-9][0-9] ]] ; then
                JOB_MAX_TIME="${2}" ; shift 2
            else
                echo -n "${PROG_NAME}: error: -t ${2}: Invalid time "
                echo -e "format, please use hh:mm:ss format\n"
                usage ; exit ${FAILURE}
            fi ;;
        --) 
            # No more options to process
            shift ; break ;;
    esac
done

# Check to see if POTCAR and CONTCAR locations were specified
if [[ ${#} -eq 2 ]] ; then
    # Regular expressions for identifying POTCAR and CONTCAR files
    PCAR_REGEX="[Pp][Oo][Tt][Cc][Aa][Rr]"
    CCAR_REGEX="[Cc][Oo][Nn][Tt][Cc][Aa][Rr]"

    # Attempt to identify POTCAR and CONTCAR argument ordering
    if [[ ${1} =~ ${PCAR_REGEX} && ${2} =~ ${CCAR_REGEX} ]] ; then
        POTCAR="${1}" ; CONTCAR="${2}" ; shift 2
    else
        POTCAR="${2}" ; CONTCAR="${1}" ; shift 2
    fi
# Accept exactly two or zero command line arguments
elif [[ ${#} -ne 0 ]] ; then
    echo "${PROG_NAME}: error: ${#}: Invalid argument count, expected [2|0]"
    echo "$@"
    exit ${FAILURE}
fi

鉴于此代码并运行应用程序,我得到以下输出:

BEFORE 
AFTER -- :hvso:l:d:n:p:t: -l help,version,submit-job,output:,library:,job-dir:,num-nodes:,num-procs:,max-time: -a -n vasp2nwchem --
vasp2nwchem: error: 7: Invalid argument count, expected [2|0]
:hvso:l:d:n:p:t: -l help,version,submit-job,output:,library:,job-dir:,num-nodes:,num-procs:,max-time: -a -n vasp2nwchem --

因此,代码进入代码的while循环部分,跳转到最后一个案例,并移出第一个--,留下我提供给{{{{}的所有参数。 1}},减去getopt标志。

任何人都可以在这个难题上获得的任何亮点都会受到极大的赞赏,因为它非常值得让我超越边缘,特别是因为这段代码功能不亚于几分钟前,现在已经完全停止了工作! !

1 个答案:

答案 0 :(得分:1)

我没有看到任何错误。我将GNU getopt安装为/usr/gnu/bin/getopt(以及getopt中的BSD /usr/bin),因此此脚本(chk.getopt.sh)几乎等同于您的开头,虽然我设置了PROG_NAME变量。这或多或少是SSCCE(Short, Self-Contained, Complete Example)的相当重要的脚本。

#!/bin/bash

PROG_NAME=$(basename $0 .sh)
SHORT_OPTS=":hvso:l:d:n:p:t:"
LONG_OPTS="help,version,submit-job,output:,library:,job-dir:"
LONG_OPTS="${LONG_OPTS},num-nodes:,num-procs:,max-time:"
OPTS=$(/usr/gnu/bin/getopt -o "${SHORT_OPTS}" -l "${LONG_OPTS}" -a -n "${PROG_NAME}" -- "$@")

# Check for invalid command line options and arguments
if [[ ${?} -ne ${SUCCESS} ]] ; then
    echo -e "${PROG_NAME}: error: Invalid option or argument\n" >&2
    usage ; exit ${FAILURE}
else
    echo "BEFORE $@"
    eval set -- ${OPTS}
    echo "AFTER $@"
fi

当我运行它时,这是输出:

$ bash -x chk.getopt.sh  -ooutput -nnumber -pperhaps -ppotato -- -o oliphaunt
++ basename chk.getopt.sh .sh
+ PROG_NAME=chk.getopt
+ SHORT_OPTS=:hvso:l:d:n:p:t:
+ LONG_OPTS=help,version,submit-job,output:,library:,job-dir:
+ LONG_OPTS=help,version,submit-job,output:,library:,job-dir:,num-nodes:,num-procs:,max-time:
++ /usr/gnu/bin/getopt -o :hvso:l:d:n:p:t: -l help,version,submit-job,output:,library:,job-dir:,num-nodes:,num-procs:,max-time: -a -n chk.getopt -- -ooutput -nnumber -pperhaps -ppotato -- -o oliphaunt
+ OPTS=' -o '\''output'\'' -n '\''number'\'' -p '\''perhaps'\'' -p '\''potato'\'' -- '\''-o'\'' '\''oliphaunt'\'''
+ [[ 0 -ne '' ]]
+ echo 'BEFORE -ooutput' -nnumber -pperhaps -ppotato -- -o oliphaunt
BEFORE -ooutput -nnumber -pperhaps -ppotato -- -o oliphaunt
+ eval set -- -o ''\''output'\''' -n ''\''number'\''' -p ''\''perhaps'\''' -p ''\''potato'\''' -- ''\''-o'\''' ''\''oliphaunt'\'''
++ set -- -o output -n number -p perhaps -p potato -- -o oliphaunt
+ echo 'AFTER -o' output -n number -p perhaps -p potato -- -o oliphaunt
AFTER -o output -n number -p perhaps -p potato -- -o oliphaunt
$

这一切看起来都是正确的;双破折号之前的选项已从参数中拆分,双破折号之后的选项正常。

因此,您的代码存在问题并不明显。即使有一个空字符串作为程序名称,它也适用于我。

您可能应该在机器上显示这么多脚本的输出吗?