【问题标题】:BASH getopt command returns its own parameters instead of command line parametersBASH getopt 命令返回它自己的参数而不是命令行参数
【发布时间】:2013-02-27 03:07:09
【问题描述】:

我正在创建一个 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 循环部分,跳转到最后一个 case,并从第一个 -- 移开,留下我提供给 getopt 的所有参数,减去-o 标志。

任何人都可以解决这个难题,我们将不胜感激,因为它真的要把我送到边缘,特别是因为这段代码至少在 3 分钟前就可以正常工作,现在已经完全停止工作了!! !

【问题讨论】:

    标签: bash parameters options flags getopt


    【解决方案1】:

    我看不出有什么问题。我将 GNU getopt 安装为 /usr/gnu/bin/getopt(和 BSD getopt 在 /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
    $
    

    这一切看起来都是正确的;双破折号之前的选项已经从它们的参数中分离出来,双破折号之后的选项都可以。

    因此,您的代码存在问题并不明显。即使使用空字符串作为程序名称,它对我来说也可以。

    也许你应该在你的机器上显示这么多脚本的输出?

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-07-14
      • 2022-07-26
      • 2013-12-28
      • 2019-12-06
      • 2021-10-30
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多