getopts 的意外行为

Erw*_*ann 3 shell-script getopts

考虑:

#!/bin/sh

while getopts ":h" o; do
  case "$o" in
    h )
    "Usage:
    sh $(basename "$0") -h      Displays help message
    sh $(basename "$0") arg     Outputs ...

     where:
    -h   help option
        arg  argument."
    exit 0
    ;;
    \? )
    echo "Invalid option -$OPTARG" 1>&2
    exit 1
    ;;
    : )
    echo "Invalid option -$OPTARG requires argument" 1>&2
    exit 1
    ;;
  esac
done
Run Code Online (Sandbox Code Playgroud)

这个调用返回not found为什么?

$ sh getopts.sh -h
getopts.sh: 12: getopts.sh: Usage:
    sh getopts.sh -h        Displays help message
    sh getopts.sh arg   Outputs ...

     where:
    -h   help option
        arg  argument.: not found
Run Code Online (Sandbox Code Playgroud)

还行吧:

$ sh getopts.sh arg
Run Code Online (Sandbox Code Playgroud)

对于这个,我期待“无效选项”:

$ sh getopts.sh
Run Code Online (Sandbox Code Playgroud)

还行吧:

$ sh getopts.sh -s x
Invalid option -s
Run Code Online (Sandbox Code Playgroud)

Ini*_*ian 5

您似乎错过了打印消息,而是将整个字符串作为要运行的命令传递。echo在字符串前添加一个

case "$o" in
  h )
  echo "Usage:
  sh $(basename "$0") -h      Displays help message
  sh $(basename "$0") arg     Outputs ...

   where:
  -h   help option
      arg  argument."
  exit 0
  ;;
Run Code Online (Sandbox Code Playgroud)

但通常更喜欢添加heredoc的样式来打印多行字符串

show_help() {
cat <<'EOF'
Usage:
    sh $(basename "$0") -h      Displays help message
    sh $(basename "$0") arg     Outputs ...

     where:
    -h   help option
        arg  argument.
EOF
}
Run Code Online (Sandbox Code Playgroud)

并使用show_help-h标志的功能。

同样对于空参数标志,第一次调用getopts()退出循环,因此循环内不能有句柄。在调用之前对空参数进行通用检查getopts()

if [ "$#" -eq 0 ]; then
    printf 'no argument flags provided\n' >&2
    exit 1
fi
Run Code Online (Sandbox Code Playgroud)

根据您之前对参数 flag 的定义:h,表明它-h不带任何参数。该子句:)仅适用于您定义-h为采用参数的情况,即定义为:h:. 只有这样,您才可以在不传递代码下:)执行的参数的情况下运行它。将整个脚本放在一起

#!/usr/bin/env bash

if [ "$#" -eq 0 ]; then
    printf 'no argument flags provided\n' >&2
    exit 1
fi

show_help() {
cat <<'EOF'
Usage:
    sh $(basename "$0") -h      Displays help message
    sh $(basename "$0") arg     Outputs ...

     where:
    -h   help option
        arg  argument.
EOF
}

while getopts ":h:" opt; do
  case "$opt" in
    h )
    show_help
    exit 1
    ;;
    \? )
    echo "Invalid option -$OPTARG" 1>&2
    exit 1
    ;;
    : )
    echo "Invalid option -$OPTARG requires argument" 1>&2
    exit 1
    ;;
  esac
done
Run Code Online (Sandbox Code Playgroud)

现在运行它

$ bash script.sh 
no argument flags provided
$ bash script.sh -h
Invalid option -h requires argument
$ bash script.sh -s
Invalid option -s
Run Code Online (Sandbox Code Playgroud)