简体   繁体   English

为什么总是执行 bash 脚本默认 case 语句?

[英]why bash script default case statement always executed?

I wrote a bash script that reads script arguments and pass them to parsearg function:我编写了一个 bash 脚本,它读取脚本参数并将它们传递给 parsearg 函数:

#!/usr/bin/env bash
function main() {
    parseargs2 "$@"
}

function parseargs2() {
    MAINCOMMAND=$1
    shift
    while [ $# -gt 0 ]; do
        case $1 in
            -s|--service) SERVICE_NAME="$2" ;;
            -r|--registry) REGISTRY="$2" ;;
            -h|--help) HELP=true ;;
            *) echo "help" && exit 1;;
        esac
        shift
    done
    echo "SERVICE_NAME: $SERVICE_NAME"
    echo "REGISTRY: $REGISTRY"
    echo "HELP: $HELP"
    echo "cmd: $MAINCOMMAND"
}

main "$@"

now when I run my script it always executes help command and then exits, I don't know why it will be ok when I remove *) case现在当我运行我的脚本时,它总是执行帮助命令然后退出,我不知道为什么当我删除*)案例时它会正常

./example.sh build --service api --registry dockerhub

EDIT: thanks to @chepner comment I found the problem I solved this by adding shift 2 at end of while loop编辑:感谢@chepner 评论,我发现我通过在 while 循环末尾添加shift 2解决了这个问题

Doing your own option parsing is a little fraught, but the idea should be to do an extra shift whenever you have an argument:做你自己的选项解析有点令人担忧,但这个想法应该是每当你有一个论点时做一个额外的shift

while [ $# -gt 0 ]; do
    case $1 in
        -s|--service) SERVICE_NAME="$2" ; shift;;
        -r|--registry) REGISTRY="$2" ; shift;;
        -h|--help) HELP=true ;;
        *) echo "help" && exit 1;;
    esac
    shift
done

You may or may not want to support a style where the single-letter version of an option has its argument jammed up against it, which works in many stock programs:您可能希望也可能不希望支持一种风格,即选项的单字母版本的参数被卡住了,这适用于许多股票程序:

while [ $# -gt 0 ]; do
    case $1 in
        -s|--service) SERVICE_NAME="$2" ; shift;;
        -s*) SERVICE_NAME=${1#-s};;
        -r|--registry) REGISTRY="$2" ; shift;;
        -r*) REGISTRY=${1#-r};;
        -h|--help) HELP=true ;;
        *) echo "help" && exit 1;;
    esac
    shift
done

Also, there's no reason to name your variables in all-caps.此外,没有理由将变量命名为全大写。 All caps is usually a sign that a variable is being export ed into the environment so some other program you're going to run can see it;全部大写通常表示变量正在被export到环境中,因此您将要运行的其他程序可以看到它; otherwise, just use lowercase.否则,只需使用小写字母。 Additionally, you don't need quotation marks on the right-hand side of an assignment, and if you're really using bash (rather than some other POSIX type shell), you likely want to use (( ... )) for numeric comparisons.此外,您不需要在赋值的右侧使用引号,如果您真的使用bash (而不是其他一些 POSIX 类型的 shell),您可能希望使用(( ... ))数值比较。

help=   # don't assume variables aren't set on entry
maincommand=$1
shift
while (( $# )); do
    case "$1" in
        -s|--service) service_name=$2 ; shift;;
        -s*) service_name=${1#-s};;
        -r|--registry) registry=$2 ; shift;;
        -r*) registry=${1#-r};;
        -h|--help) help=true ;;
        *) echo "help" && exit 1;;
    esac
    shift
done
for var in service_name registry help maincommand; do
   printf '%s: "%s"\n' "$var" "${!var}"
done

FWIW, true is just a string to the shell with no special significance; FWIW, true只是 shell 的一个字符串,没有特殊意义; the shell doesn't have Boolean values beyond "command succeeded/failed" (which is just zero/nonzero on the exit code) or Boolean operators other than the ones that operate on commands (eg command1 && run this if command1 succeeded ).除了“命令成功/失败”(退出代码上只是零/非零)或对命令进行操作的布尔运算符(例如command1 && run this if command1 succeeded )之外,shell 没有布尔值。 So when flags are stored in shell variables the Booleanness is usually represented either by empty vs. nonempty string (and true is a fine value to use for the nonempty case) or 0 vs. 1 (or 0 vs nonzero) number.因此,当标志存储在 shell 变量中时,布尔值通常由空与非空字符串表示(并且true是用于非空情况的一个很好的值)或 0 与 1(或 0 与非零)数字。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM