我有一个用这一行调用的脚本:
./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?
$v
$f
$d
true
$outFile
/fizz/someOtherFile
--option argument
cat >/tmp/demo-space-separated.sh <<'EOF' #!/bin/bash POSITIONAL_ARGS=() while [[ $# -gt 0 ]]; do case $1 in -e|--extension) EXTENSION="$2" shift # past argument shift # past value ;; -s|--searchpath) SEARCHPATH="$2" shift # past argument shift # past value ;; --default) DEFAULT=YES shift # past argument ;; -*|--*) echo "Unknown option $1" exit 1 ;; *) POSITIONAL_ARGS+=("$1") # save positional arg shift # past argument ;; esac done set -- "${POSITIONAL_ARGS[@]}" # restore positional parameters echo "FILE EXTENSION = ${EXTENSION}" echo "SEARCH PATH = ${SEARCHPATH}" echo "DEFAULT = ${DEFAULT}" echo "Number files in SEARCH PATH with EXTENSION:" $(ls -1 "${SEARCHPATH}"/*."${EXTENSION}" | wc -l) if [[ -n $1 ]]; then echo "Last line of file specified as non-opt/last argument:" tail -1 "$1" fi EOF chmod +x /tmp/demo-space-separated.sh /tmp/demo-space-separated.sh -e conf -s /etc /etc/hosts
FILE EXTENSION = conf SEARCH PATH = /etc DEFAULT = Number files in SEARCH PATH with EXTENSION: 14 Last line of file specified as non-opt/last argument: #93.184.216.34 example.com
demo-space-separated.sh -e conf -s /etc /etc/hosts
--option=argument
cat >/tmp/demo-equals-separated.sh <<'EOF' #!/bin/bash for i in "$@"; do case $i in -e=*|--extension=*) EXTENSION="${i#*=}" shift # past argument=value ;; -s=*|--searchpath=*) SEARCHPATH="${i#*=}" shift # past argument=value ;; --default) DEFAULT=YES shift # past argument with no value ;; -*|--*) echo "Unknown option $i" exit 1 ;; *) ;; esac done echo "FILE EXTENSION = ${EXTENSION}" echo "SEARCH PATH = ${SEARCHPATH}" echo "DEFAULT = ${DEFAULT}" echo "Number files in SEARCH PATH with EXTENSION:" $(ls -1 "${SEARCHPATH}"/*."${EXTENSION}" | wc -l) if [[ -n $1 ]]; then echo "Last line of file specified as non-opt/last argument:" tail -1 $1 fi EOF chmod +x /tmp/demo-equals-separated.sh /tmp/demo-equals-separated.sh -e=conf -s=/etc /etc/hosts
demo-equals-separated.sh -e=conf -s=/etc /etc/hosts
为了更好地理解在本指南${i#*=}中搜索“子字符串删除” 。它在功能上等价于调用一个不需要的子进程或调用两个不需要的子进程。sed 's/[^=]*=//' <<< "$i"````echo "$i" | sed 's/[^=]*=//'
${i#*=}
sed 's/[^=]*=//' <<< "$i"````echo "$i" | sed 's/[^=]*=//'
getopt(1) 限制(较旧、相对较新的getopt版本):
getopt
较新的getopt版本没有这些限制。有关更多信息,请参阅这些文档。
此外,POSIX shell 和其他提供getopts的没有这些限制。我已经包括了一个简单的getopts例子。
getopts
cat >/tmp/demo-getopts.sh <<'EOF' #!/bin/sh # A POSIX variable OPTIND=1 # Reset in case getopts has been used previously in the shell. # Initialize our own variables: output_file="" verbose=0 while getopts "h?vf:" opt; do case "$opt" in h|\?) show_help exit 0 ;; v) verbose=1 ;; f) output_file=$OPTARG ;; esac done shift $((OPTIND-1)) [ "${1:-}" = "--" ] && shift echo "verbose=$verbose, output_file='$output_file', Leftovers: $@" EOF chmod +x /tmp/demo-getopts.sh /tmp/demo-getopts.sh -vf /etc/hosts foo bar
verbose=1, output_file='/etc/hosts', Leftovers: foo bar
demo-getopts.sh -vf /etc/hosts foo bar
的优点getopts是:
dash
-vf filename
的缺点getopts是它只能处理短选项(-h, not --help)而无需额外代码。
-h
--help