0

我正在创建一个 BASH 脚本并使用 BASHgetopt命令来解析命令行参数。不是返回命令行上提供的参数,而是返回提供给命令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循环部分,跳转到最后一种情况,并从第一种情况转移--,留下我提供给的所有参数getopt,减去-o标志。

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

4

1 回答 1

1

我看不出有什么不对。我将 GNUgetopt安装为/usr/gnu/bin/getopt(和 BSDgetopt/usr/bin),所以这个脚本 ( chk.getopt.sh) 几乎等同于你的开始,尽管我确实设置了PROG_NAME变量。这或多或少是您相当充实的脚本的 SSCCE(简短、自包含、完整示例)。

#!/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
$

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

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

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

于 2013-02-27T04:06:22.863 回答