代码:cmd.sh
#!/bin/bash
if [ $# -ne 4 ]; then
echo not 4
exit 1
fi
while [[ $# > 1 ]]
do
key="$1"
case $key in
-f|--file)
FILE="$2"
shift
;;
-t|--type)
TYPE="$2"
shift
;;
--default)
DEFAULT=YES
;;
*)
# unknown option
;;
esac
shift
done
echo FILE = "${FILE}"
echo TYPE = "${TYPE}"
目标
如何确保用户始终必须输入file
和type
个参数,并确保他们始终输入2 arguments
,而不是更多而不是更少。
修改
由于标志,更新了上面的代码,ne 4。
仅有效结果
$ ./cmd.sh -f asd -t def
FILE = asd
TYPE = def
当前问题
1
$ ./cmd.sh -f asd asd asd
FILE = asd
TYPE =
我没有包含-t标志但它仍然认为它是有效的。
2
$ ./cmd.sh -f asd -g asd
FILE = asd
TYPE =
我包含了无效的标记,但仍认为它有效。
解
#!/bin/bash
if [ $# -ne 4 ]; then
echo not 4
exit 1
fi
while [[ $# > 1 ]]
do
key="$1"
case $key in
-f|--file)
FILE="$2"
shift
;;
-t|--type)
TYPE="$2"
shift
;;
--default)
DEFAULT=YES
;;
*)
echo invalid option $key
exit 1
;;
esac
shift
done
echo FILE = "${FILE}"
echo TYPE = "${TYPE}"
最后一期
如何忽略长度要求并检查它们是否键入-h或--help?我希望在这种情况下打印出用法。
MY ATTEMPT
#!/bin/bash
# Ensure that environment variables are not used by accident
FILE=
TYPE=
arg0="$(basename "$0" .sh)"
usage() { echo "Usage: $arg0 -f file -t type" >&2; exit 1; }
error() { echo "$arg0: $*" >&2; usage; }
help() { echo "Help: some help file" >&1; exit 0; }
version() { echo "Version: 1.0" >&1; exit 0; }
while [ $# -gt 1 ]
do
case "$1" in
-h|--help)
help
;;
-v|--version)
version
;;
-f|--file|-t|--type)
;;
-*) error "unrecognized option $1";;
*) error "unexpected non-option argument $1";;
esac
shift
done
[ $# -eq 4 ] || usage
while [ $# -gt 1 ]
do
case "$1" in
-f|--file)
[ -z "$FILE" ] || error "already specified file name $FILE"
[ -z "$2" ] && error "empty file name specified after $1"
FILE="$2"
shift
;;
-t|--type)
[ -z "$TYPE" ] || error "already specified file type $TYPE"
[ -z "$2" ] && error "empty type name specified after $1"
TYPE="$2"
shift
;;
-*) error "unrecognized option $1";;
*) error "unexpected non-option argument $1";;
esac
shift
done
# Should never execute either of these errors
[ -z "$FILE" ] && error "no file name specified"
[ -z "$TYPE" ] && error "no type name specified"
echo FILE = "${FILE}"
echo TYPE = "${TYPE}"
这破坏了代码并开始抛出以下错误:
$ bash a2.sh -f typename -t asda
a2: unexpected non-option argument typename
Usage: a2 -f file -t type
下面的解决方案比我试图做的更优雅!
更新 - 测试
$ bash d2.sh -t type -f filename -V
FILE = filename
TYPE = type
$ bash d2.sh -h
d2.sh: no file name specified (and no --default)
Usage: d2 [-d|--default][-h|--help][-V|--version][{-f|--file} file] [{-t|--type} type]
$ bash d2.sh -V
d2.sh: no file name specified (and no --default)
Usage: d2 [-d|--default][-h|--help][-V|--version][{-f|--file} file] [{-t|--type} type]
答案 0 :(得分:2)
您已经在检查是否有任何参数,所以您是否尝试检查是否有多于或少于2?
if [ $# -ne 2 ]; then
# TODO: print usage
exit 1
fi
# rest of code here
答案 1 :(得分:1)
这符合您的要求吗?我认为它涵盖了大多数基础,但如果您选择将一个空格或制表符串指定为文件名或类型名称,则脚本不会反对。
a2.sh
#!/bin/bash
# Ensure that environment variables are not used by accident
FILE=
TYPE=
arg0="$(basename "$0" .sh)"
usage() { echo "Usage: $arg0 -f file -t type" >&2; exit 1; }
error() { echo "$arg0: $*" >&2; usage; }
[ $# -eq 4 ] || usage
while [ $# -gt 1 ]
do
case "$1" in
-f|--file)
[ -z "$FILE" ] || error "already specified file name $FILE"
[ -z "$2" ] && error "empty file name specified after $1"
FILE="$2"
shift
;;
-t|--type)
[ -z "$TYPE" ] || error "already specified file type $TYPE"
[ -z "$2" ] && error "empty type name specified after $1"
TYPE="$2"
shift
;;
-*) error "unrecognized option $1";;
*) error "unexpected non-option argument $1";;
esac
shift
done
# Should never execute either of these errors
[ -z "$FILE" ] && error "no file name specified"
[ -z "$TYPE" ] && error "no type name specified"
echo FILE = "${FILE}"
echo TYPE = "${TYPE}"
请注意,如果脚本中未初始化FILE
和TYPE
,则运行:
FILE=henry TYPE=ford bash a2.sh -f file -t type
会生成错误,因为FILE
已经有一个值(或TYPE
已经有一个具有不同参数的值)。确保您不会意外地获取环境变量非常重要。还有一种情况是说你的脚本中的变量应该是小写的(或者是大小写的),留下大写的环境变量。但是,您仍然需要设置小写变量 - 您可以轻松地将小写环境变量设置为大写,尽管大写是常规变量。
另请注意$*
功能中error
的谨慎,慎重和正确使用。虽然使用$@
不会造成麻烦,但这次所需的结果是单个字符串,$*
给出了这一点。 (通常,使用"$@"
是正确的,但这是"…$*…"
更好的情况。)
$ bash a2.sh
Usage: a2 -f file -t type
$ bash a2.sh a
Usage: a2 -f file -t type
$ bash a2.sh a b
Usage: a2 -f file -t type
$ bash a2.sh a b c
Usage: a2 -f file -t type
$ bash a2.sh a b c d
a2.sh: unexpected non-option argument a
Usage: a2 -f file -t type
$ bash a2.sh a b c d e
Usage: a2 -f file -t type
$ bash a2.sh -f file -f file
a2: already specified file name file
Usage: a2 -f file -t type
$ bash a2.sh -t type -t typename
a2: already specified file type type
Usage: a2 -f file -t type
$ bash a2.sh -t type t typename
a2: unexpected non-option argument t
Usage: a2 -f file -t type
$ bash a2.sh -t type -k typename
a2: unrecognized option -k
Usage: a2 -f file -t type
$ bash a2.sh -t type -f filename
FILE = filename
TYPE = type
$ bash a2.sh --file firstname -f filename
a2: already specified file name firstname
Usage: a2 -f file -t type
$ bash a2.sh --type typename -t type
a2: already specified file type typename
Usage: a2 -f file -t type
$ bash a2.sh -f '' -t ''
a2: empty file name specified after -f
Usage: a2 -f file -t type
$ bash a2.sh -t '' -f ''
a2: empty type name specified after -t
Usage: a2 -f file -t type
$
--help
,--version
,--default
等另见评论链(工作中的懒惰)。修订版的代码可能是:
#!/bin/bash
# Ensure that environment variables are not used by accident
FILE=
TYPE=
arg0="$(basename "$0" .sh)"
usemsg="Usage: $arg0 [-d|--default][-h|--help][-V|--version][{-f|--file} file] [{-t|--type} type]"
usage() { echo "$usemsg" >&2; exit 1; }
error() { echo "$0: $*" >&2; usage; }
while [ $# -gt 0 ]
do
case "$1" in
-f|--file)
[ -z "$FILE" ] || error "already specified file name $FILE"
[ -z "$2" ] && error "empty file name specified after $1"
FILE="$2"
shift
;;
-t|--type)
[ -z "$TYPE" ] || error "already specified file type $TYPE"
[ -z "$2" ] && error "empty type name specified after $1"
TYPE="$2"
shift
;;
-h|--help)
echo "$usemsg"
echo ""
echo " [-f|--file] filename Use the specified file name"
echo " [-t|--type] typename Use the specified type name"
echo " [-h|--help] Print this help message and exit"
echo " [-V|--version] Print the version information and exit"
echo " [-d|--default] Use the defaults (default-file and default-type)"
exit 0
;;
-V|--version)
echo "$arg0 Version 1.02 (2016-03-18)"
exit 0
;;
-d|--default)
[ -z "$FILE" ] && FILE="default-file"
[ -z "$TYPE" ] && TYPE="default-type"
;;
-*) error "unrecognized option $1";;
*) error "unexpected non-option argument $1";;
esac
shift
done
[ -z "$FILE" ] && error "no file name specified (and no --default)"
[ -z "$TYPE" ] && error "no type name specified (and no --default)"
echo FILE = "${FILE}"
echo TYPE = "${TYPE}"