我正在编写一个 shell 脚本,最多接受 2 个选项。但是,我有一个问题。你能帮我吗? (假设该脚本的名称是command
。)
#!/bin/bash
PROGNAME=$(basename $0)
for OPT in "$@"
do
echo "OPT: $OPT"
case "$OPT" in
'-p' | '--password' )
if [[ -z "$2" ]] || [[ "$2" =~ ^-+ ]]
then
echo "$PROGNAME: option requires an argument -- '$(echo $1 | sed 's/^-*//')'"
exit 2
fi
PASSWORD="$2"
shift 2
;;
'-u' | '--user' )
if [[ -z "$2" ]] || [[ "$2" =~ ^-+ ]]
then
echo "$PROGNAME: option requires an argument -- '$(echo $1 | sed 's/^-*//')'"
exit 2
fi
USER="$2"
shift 2
;;
* )
echo "$1"
echo "$PROGNAME: illigal option or argument -- '$(echo $1 | sed 's/^-*//')'"
exit 1
;;
esac
done
echo "GOOD"
测试1
$./command
GOOD
测试2
$./command -u user
OPT: -u
OPT: user
command: illigal option or argument -- ''
(第四行是空的。)
测试3
$./command -u user -p passwd
OPT: -u
OPT: user
-p
command: illigal option or argument -- 'p'
所有 -u、--user、-p 和 --password 都会发生同样的情况。我有 3 个问题。
1)为什么test2和test3中会出现“OPT:user”?
2)如果我给它一个选项,为什么这段代码会导致错误?
3)如何修复此代码?我真的很感谢你的帮助!
答案1
你的扩展"$@"
发生在循环的开始for
;内部shift
不会有任何影响。
例如
for a in "$@"
do
echo OPTION: $a
shift 2
done
有了这个:
$ bash x a b c d e f
OPTION: a
OPTION: b
OPTION: c
OPTION: d
OPTION: e
OPTION: f
我们可以看到shift
没有做任何事情
相反,您希望每次都重新评估它:
$ cat x
while [ $# -gt 0 ]
do
a="$1"
echo OPTION: $a
shift 2
done
$ bash x a b c d e f
OPTION: a
OPTION: c
OPTION: e
(您需要做比这更好的测试;如果您传递奇数个参数,则此示例代码永远不会终止,因为失败shift 2
)
答案2
我曾经使用 while/shift 循环
#! /bin/bash
PROGNAME=$(basename $0)
while [ -n "$1" ]
do
echo "OPT: $1"
case "$1" in
--user=* )
if [[ "$1" =~ --user=(.+) ]]
then
USER=${BASH_REMATCH[1]}
else
echo "$PROGNAME: option requires an argument -- $1"
exit 2
fi
;;
-u )
if [ -z "$2" ]
then
echo "$PROGNAME: option requires an argument -- $1"
exit 2
fi
USER="$2"
shift
;;
* )
echo "$PROGNAME: illigal option or argument -- $1"
exit 1
;;
esac
shift
done
[ -n "$USER" ] && echo "USER: $USER"
echo "GOOD"
但$USER
它是一个坏变量,因为它已经设置了。