假设我有一个用以下行调用的脚本:./myscript -vfd ./foo/bar/someFile -o /fizz/someOtherFile 或者这个:./myscript -v -f -d -o /fizz/someOtherFile ./foo/bar/someFile 什么是...
假设我有一个用以下行调用的脚本:
./myscript -vfd ./foo/bar/someFile -o /fizz/someOtherFile
或者这个:
./myscript -v -f -d -o /fizz/someOtherFile ./foo/bar/someFile
解析此问题的一种可接受的方式是什么,使得在每种情况下(或两者的某种组合) $v
, $f
,和 $d
都将被设置为 true
并且 $outFile
等于 /fizz/someOtherFile
?
No answer showcases enhanced getopt . And the top-voted answer is misleading: 它要么忽略 -vfd
样式短选项(由OP要求),要么忽略位置参数后的选项(也是由OP要求);并且它忽略了解析错误。 相反:
getopt
from util-linux or formerly GNU glibc .1
getopt_long()
一起工作
getopt
can’t do this) script.sh -o outFile file1 file2 -v
( getopts
doesn’t do this) =
-style long options: script.sh --outfile=fileOut --infile fileIn
(allowing both is lengthy if self parsing) -vfd
(real work if self parsing) -oOutfile
or -vfdoOutfile
getopt --test
→返回值 4。
getopt
或 shell 内置的 getopts
用途有限。
以下调用
myscript -vfd ./foo/bar/someFile -o /fizz/someOtherFile
myscript -v -f -d -o/fizz/someOtherFile -- ./foo/bar/someFile
myscript --verbose --force --debug ./foo/bar/someFile -o/fizz/someOtherFile
myscript --output=/fizz/someOtherFile ./foo/bar/someFile -vfd
myscript ./foo/bar/someFile -df -v --output /fizz/someOtherFile
全部返回
verbose: y, force: y, debug: y, in: ./foo/bar/someFile, out: /fizz/someOtherFile
以下内容 myscript
#!/bin/bash
# More safety, by turning some bugs into errors.
set -o errexit -o pipefail -o noclobber -o nounset
# ignore errexit with `&& true`
getopt --test > /dev/null && true
if [[ $? -ne 4 ]]; then
echo 'I’m sorry, `getopt --test` failed in this environment.'
exit 1
fi
# option --output/-o requires 1 argument
LONGOPTS=debug,force,output:,verbose
OPTIONS=dfo:v
# -temporarily store output to be able to check for errors
# -activate quoting/enhanced mode (e.g. by writing out “--options”)
# -pass arguments only via -- "$@" to separate them correctly
# -if getopt fails, it complains itself to stdout
PARSED=$(getopt --options=$OPTIONS --longoptions=$LONGOPTS --name "$0" -- "$@") || exit 2
# read getopt’s output this way to handle the quoting right:
eval set -- "$PARSED"
d=n f=n v=n outFile=-
# now enjoy the options in order and nicely split until we see --
while true; do
case "$1" in
-d|--debug)
d=y
shift
;;
-f|--force)
f=y
shift
;;
-v|--verbose)
v=y
shift
;;
-o|--output)
outFile="$2"
shift 2
;;
--)
shift
break
;;
*)
echo "Programming error"
exit 3
;;
esac
done
# handle non-option arguments
if [[ $# -ne 1 ]]; then
echo "$0: A single input file is required."
exit 4
fi
echo "verbose: $v, force: $f, debug: $d, in: $1, out: $outFile"
1增强型 getopt 适用于大多数“bash 系统”,包括 Cygwin;在 OS X 上尝试 brew install gnu-getopt
, brew install util-linux
or sudo port install getopt
2POSIX exec()
约定没有可靠的方法在命令行参数中传递二进制 NULL;这些字节过早地结束了参数
3第一个版本于 1997 年或之前发布(我只追溯到 1997 年)