在不使用getopts的情况下,在Shell脚本中添加用法内容

11

我有一个脚本,如果用户在执行脚本时缺少任何必需的信息,我需要显示使用命令。

Usage : Script -s <server> -i <instance> -u <user> -p <password> <query> -w <warning value> -c <critical value>

带有关于所有OPTIONS的说明。

我正在以以下变量形式从参数中获取值。但我希望在Shell脚本中进行验证后再使用此用法。

SERVER=$1
INSTANCE=$2
USER=$3
DB_PASSWD=$4
QUERY=$5
VAL_WARN=$6
VAL_CRIT=$7

我尝试过使用getopts,但由于传递值之前<query>没有-q参数,所以无法使用。

我已经尝试找到所有其他方法,但每个人都建议使用getopts,这对我来说不是可行的解决方案。

请帮帮我。


1
选项字母的优点之一是它允许用户以任何顺序放置项目。如果顺序固定,则无需使用 -s 等选项;这只会使用户额外输入而没有实际好处。我注意到在原始命令行中,服务器字符串为 $2(而不是 $1)。您能否规范化您的命令,以便需要 -q,或者查询是最后一个参数?任何选项都有合理的默认值吗?如果有,请使用它们,而不是要求用户键入 13 个参数。您的用户将感谢您,并且您的脚本将更容易编写。 - Jonathan Leffler
5个回答

23

使用 shift 命令来迭代所有参数,例如:

#!/bin/sh

usage ()
{
  echo 'Usage : Script -s <server> -i <instance> -u <user> -p <password>'
  echo '                  <query> -w <warning value> -c <critical value>'
  exit
}

if [ "$#" -ne 13 ]
then
  usage
fi

while [ "$1" != "" ]; do
case $1 in
        -s )           shift
                       SERVER=$1
                       ;;
        -i )           shift
                       INSTANCE=$1
                       ;;
        -u )           shift
                       USER=$1
                       ;;
        -p )           shift
                       PASSWORD=$1
                       ;;
        -w )           shift
                       WARNINGVAL=$1
                       ;;
        -c )           shift
                       CRITICVAL=$1
                       ;;
        * )            QUERY=$1
    esac
    shift
done

# extra validation suggested by @technosaurus
if [ "$SERVER" = "" ]
then
    usage
fi
if [ "$INSTANCE" = "" ]
then
    usage
fi
if [ "$USER" = "" ]
then
    usage
fi
if [ "$PASSWORD" = "" ]
then
    usage
fi
if [ "$QUERY" = "" ]
then
    usage
fi
if [ "$WARNINGVAL" = "" ]
then
    usage
fi
if [ "$CRITICVAL" = "" ]
then
    usage
fi

echo "ALL IS WELL. SERVER=$SERVER,INSTANCE=$INSTANCE,USER=$USER,PASSWORD=$PASSWORD,QUERY=$QUERY,WARNING=$WARNINGVAL,CRITIC=$CRITICVAL"

应该会有用。

编辑:根据@technosaurus的建议,脚本中添加了参数验证。


只需要在结尾处添加检查 [ ! "$PASSWORD" ] && usage #对于其他必需参数也类似 - technosaurus
@technosaurus 我看到检查已经在那里了:while [ "$1" != "" ] ... - just somebody
这仍然可以工作 Script q q q q q q q q q q q q q,并且没有设置任何所需的值。 - technosaurus
@technosaurus 你的两条评论都是正确的。我已经相应地更新了脚本(我误读了原始问题,一开始只考虑了解析)。 :) - matt.nguyen
@matt.nguyen 我没有测试过,但是应该是 == 或 -eq 吧?(我忘记哪个是字符串/数字了)... 但是要测试变量是否设置,我通常只需使用 [ "$VAR" ] || usage ... 如果一个变量是可选的,但需要设置为“某些值”,则可以使用 ${VAR:-默认值} ... 我猜这可能适用于其中一些情况。 - technosaurus
@technosaurus 请看(https://dev59.com/UXA75IYBdhLWcg3wfpKr) :). 我选择更详细地解释,因为我觉得这对OP更有帮助(我可能在这一点上错了)。 - matt.nguyen

1

getopts抱怨有充分的理由。你应该改变脚本的接口以符合人们的期望。

或者,你可以使用getopts两次,首先用于前置query选项,shift,然后再用于其余选项。


1
尝试这个。
usage()
{
   echo "$0 -s <server> -i <instance> -u <user> -p <password> <query> -w <warning value> -c <critical value>"
}

for i in {0..12}
do
    arg=`expr $i +1`
    test ! "${!arg}" && usage && break
done

希望这有所帮助。

1
或者你可以使用 for i in {1..13} 的方式,避免使用子shell。 - just somebody

0

这是一种非标准的方法,但我发现它非常有用。不必将值作为参数传递给特定的标志(这相当烦人;用户不应该被要求指定每个值,但应提供合理的默认值),而是可以直接通过环境变量传递它们,这样典型的调用看起来像:

SERVER=blah INSTANCE=foo Script 

如果您使用小写的变量名,这会很好,因为用户不必大喊大叫。这使得脚本可以完全避免解析命令行,因为变量的值将在脚本开始时设置。


0

嗯,一个非常原始的方法就是这样

usage ()
{
  echo 'Usage : Script -s <server> -i <instance> -u <user> -p <password>'
  echo '                  <query> -w <warning value> -c <critical value>'
  exit
}

[ ${13} ] || usage

谢谢。现在,如果用户在执行时不提供13个参数,我可以处理了。但是另外,我会收到一些丑陋的错误消息,比如“line 76: [: 21: unary operator expected”,因为这些参数是必须的。我该怎么避免这种情况? - San

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接