我正在尝试创建一个脚本,该脚本将带有一个带有可选选项的标志。使用 getopts 可以在标志之后指定一个强制参数(使用冒号),但我想保持它是可选的。
它会是这样的:
./install.sh -a 3
或者
./install.sh -a3
其中“a”是标志,“3”是 a 后面的可选参数。
提前致谢。
外部程序通过getopt
在选项名称中添加双冒号来允许选项具有单个可选参数。
# Based on a longer example in getopt-parse.bash, included with
# getopt
TEMP=$(getopt -o a:: -- "$@")
eval set -- "$TEMP"
while true ; do
case "$1" in
-a)
case "$2" in
"") echo "Option a, no argument"; shift 2 ;;
*) echo "Option a, argument $2"; shift 2;;
esac ;;
--) shift; break ;;
*) echo "Internal error!"; exit 1 ;;
esac
done
以下是没有的getopt
,它需要一个带有 -a 标志的可选参数:
for WORD; do
case $WORD in
-a?) echo "single arg Option"
SEP=${WORD:2:1}
echo $SEP
shift ;;
-a) echo "split arg Option"
if [[ ${2:0:1} != "-" && ${2:0:1} != ""]] ; then
SEP=$2
shift 2
echo "arg present"
echo $SEP
else
echo "optional arg omitted"
fi ;;
-a*) echo "arg Option"
SEP=${WORD:2}
echo $SEP
shift ;;
-*) echo "Unrecognized Short Option"
echo "Unrecognized argument"
;;
esac
done
其他选项/标志也可以轻松添加。
使用 getopt 功能。在大多数系统上,man getopt
将为它生成文档,甚至在脚本中使用它的示例。从我系统上的手册页:
以下代码片段显示了如何处理可以采用选项 -a 和 -b 以及需要参数的选项 -o 的命令的参数。
args=`getopt abo: $*`
# you should not use `getopt abo: "$@"` since that would parse
# the arguments differently from what the set command below does.
if [ $? != 0 ]
then
echo 'Usage: ...'
exit 2
fi
set -- $args
# You cannot use the set command with a backquoted getopt directly,
# since the exit code from getopt would be shadowed by those of set,
# which is zero by definition.
for i
do
case "$i"
in
-a|-b)
echo flag $i set; sflags="${i#-}$sflags";
shift;;
-o)
echo oarg is "'"$2"'"; oarg="$2"; shift;
shift;;
--)
shift; break;;
esac
done
echo single-char flags: "'"$sflags"'"
echo oarg is "'"$oarg"'"
此代码将接受以下任何等效项:
cmd -aoarg file file
cmd -a -o arg file file
cmd -oarg -a file file
cmd -a -oarg -- file file
在 bash 中有一些隐式变量:
$#: contains number of arguments for a called script/function
$0: contains names of script/function
$1: contains first argument
$2: contains second argument
...
$n: contains n-th argument
例如:
#!/bin/ksh
if [ $# -ne 2 ]
then
echo "Wrong number of argument - expected 2 : $#"
else
echo "Argument list:"
echo "\t$0"
echo "\t$1"
echo "\t$2"
fi
我的解决方案:
#!/bin/bash
count=0
skip=0
flag="no flag"
list=($@) #put args in array
for arg in $@ ; do #iterate over array
count=$(($count+1)) #update counter
if [ $skip -eq 1 ]; then #check if we have to skip this args
skip=0
continue
fi
opt=${arg:0:2} #get only first 2 chars as option
if [ $opt == "-a" ]; then #check if option equals "-a"
if [ $opt == $arg ] ; then #check if this is only the option or has a flag
if [ ${list[$count]:0:1} != "-" ]; then #check if next arg is an option
skip=1 #skip next arg
flag=${list[$count]} #use next arg as flag
fi
else
flag=${arg:2} #use chars after "-a" as flag
fi
fi
done
echo $flag