case 语句中的内联分组命令不起作用:意外标记“;;”附近存在语法错误

case 语句中的内联分组命令不起作用:意外标记“;;”附近存在语法错误

在我的 bash 脚本中,我解析参数。我想尝试只允许一个参数没有特定的模式,即“路径”。任何其他不符合情况的参数都应该导致脚本退出。这是一个例子:

#!/bin/bash
while [ "$#" -gt 0 ]; do
    case "$1" in
        -v|--verbose) verbose=1 ;;
        -h|--help)
            echo "Usage: $(basename "$0") [OPTIONS] [PATH]"
            echo "Does something interesting with the given path."
            echo ""
            echo "OPTIONS"
            echo "  -v,   --verbose                 Prints verbose information."
            echo "  -h,   --help                    Prints this help message."
            exit 0
            ;;
        *) { test -z $path && path=$1 } || { echo "Invalid command line flag $1" >&2 && exit 1 } ;;
    esac
    shift
done

然而该行{ test -z $path && path=$1 } || { echo "Invalid command line flag $1" >&2 && exit 1 } ;;失败并显示:

myscript: line 14 syntax error near unexpected token `;;'
myscript: line 14: `           *) { test -z $path && path=$1 } || { echo "Invalid command line flag $1" >&2 && exit 1 } ;;'

我知道我可以简单地构建一个 if-else 语句,但我想知道为什么我不能将其内联分组。如果我删除花括号,则exit 1始终会到达。

答案1

单行命令组内的命令列表本身必须以分号终止,{ list; }否则{ list }

例如,

$ bash -c 'case $1 in *) { echo foo && echo bar } ;; esac' bash baz
bash: -c: line 0: syntax error near unexpected token `;;'
bash: -c: line 0: `case $1 in *) { echo foo && echo bar } ;; esac'

失败,

$ bash -c 'case $1 in *) { echo foo && echo bar; } ;; esac' bash baz
foo
bar

成功了。

命令列表和 } 之间的分隔符以及 bash 手册的部分命令分组

答案2

前面的答案和评论涉及错误的主要来源。

我发布了一个建议,将多行使用消息移至脚本的另一部分(例如子例程),并让您的-h|-help)子句简单地调用子例程:

USAGE () {
  echo "This is the first line of my usage message"
  echo "This is another line"
  echo "Etc."
}

(farther down the script)

case "$1" in
    -v|--verbose) verbose=1 ;;
       -h|--help) USAGE ; exit 0 ;;
               *) # your code here ;;
esac

或者您可以使用here文档将多行使用消息组装成字符串变量,然后case语句子句显示该变量并退出。

# fill $USAGE with a here document that isn't indented
USAGE=$(cat - <<EOUSAGE
Usage: $(basename "$0") [OPTIONS] [PATH]
Does something interesting with the given path.

OPTIONS
  -v,   --verbose                 Prints verbose information.
  -h,   --help                    Prints this help message.
EOUSAGE
)  # USAGE=$( ... ) ends here

(farther down the script)

case "$1" in
  -v|--verbose) verbose=1 ;;
     -h|--help) echo "$USAGE" ; exit 0 ;;
             *) # your code here ;;
esac

我倾向于使用此处文档方法,因为编写多行消息远不如多个 echo 命令那么混乱,而且文本中的空行或引号也不会有问题。此外,由于它没有缩进,您可以看到每行在终端窗口中延伸了多远,并且可以将较长的行换行以获得更好的易读性。

相关内容