问题描述
说,我有一个脚本,用这一行调用:
Say, I have a script that gets called with this line:
./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
?
What's the accepted way of parsing this such that in each case (or some combination of the two) $v
, $f
, and $d
will all be set to true
and $outFile
will be equal to /fizz/someOtherFile
?
推荐答案
Bash Space-Separated(例如,--option argument
)
cat >/tmp/demo-space-separated.sh <<'EOF'
#!/bin/bash
POSITIONAL=()
while [[ $# -gt 0 ]]; do
key="$1"
case $key in
-e|--extension)
EXTENSION="$2"
shift # past argument
shift # past value
;;
-s|--searchpath)
SEARCHPATH="$2"
shift # past argument
shift # past value
;;
-l|--lib)
LIBPATH="$2"
shift # past argument
shift # past value
;;
--default)
DEFAULT=YES
shift # past argument
;;
*) # unknown option
POSITIONAL+=("$1") # save it in an array for later
shift # past argument
;;
esac
done
set -- "${POSITIONAL[@]}" # restore positional parameters
echo "FILE EXTENSION = ${EXTENSION}"
echo "SEARCH PATH = ${SEARCHPATH}"
echo "LIBRARY PATH = ${LIBPATH}"
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 -l /usr/lib /etc/hosts
复制粘贴上面块的输出
FILE EXTENSION = conf
SEARCH PATH = /etc
LIBRARY PATH = /usr/lib
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 -l /usr/lib /etc/hosts
Bash Equals-Separated(例如,--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
;;
-l=*|--lib=*)
LIBPATH="${i#*=}"
shift # past argument=value
;;
--default)
DEFAULT=YES
shift # past argument with no value
;;
*)
# unknown option
;;
esac
done
echo "FILE EXTENSION = ${EXTENSION}"
echo "SEARCH PATH = ${SEARCHPATH}"
echo "LIBRARY PATH = ${LIBPATH}"
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 -l=/usr/lib /etc/hosts
复制粘贴上面块的输出
FILE EXTENSION = conf
SEARCH PATH = /etc
LIBRARY PATH = /usr/lib
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-equals-separated.sh -e=conf -s=/etc -l=/usr/lib /etc/hosts
为了更好地理解 ${i#*=}
搜索Substring Removal"在本指南中.它在功能上等同于 `sed 's/[^=]*=//' <<<$i"`
调用不必要的子进程或 `echo $i"|sed 's/[^=]*=//'`
调用两个不必要的子进程.
To better understand ${i#*=}
search for "Substring Removal" in this guide. It is functionally equivalent to `sed 's/[^=]*=//' <<< "$i"`
which calls a needless subprocess or `echo "$i" | sed 's/[^=]*=//'`
which calls two needless subprocesses.
getopt(1) 限制(较旧的、相对较新的 getopt
版本):
getopt(1) limitations (older, relatively-recent getopt
versions):
- 无法处理空字符串的参数
- 无法处理带有嵌入空格的参数
最近的 getopt
版本没有这些限制.有关详细信息,请参阅这些文档.
More recent getopt
versions don't have these limitations. For more information, see these docs.
此外,POSIX shell 和其他 shell 提供了没有这些限制的 getopts
.我已经包含了一个简单的 getopts
示例.
Additionally, the POSIX shell and others offer getopts
which doen't have these limitations. I've included a simplistic getopts
example.
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
的优点是:
- 它更便于携带,并且可以在其他 shell 中使用,例如
dash
. - 它可以以典型的 Unix 方式自动处理多个单个选项,例如
-vf 文件名
.
getopts
的缺点是它只能处理短选项(-h
,而不是 --help
)而没有附加代码.
The disadvantage of getopts
is that it can only handle short options (-h
, not --help
) without additional code.
有一个 getopts 教程,其中解释了所有语法和变量的含义.在 bash 中,还有 help getopts
,它可能提供信息.
There is a getopts tutorial which explains what all of the syntax and variables mean. In bash, there is also help getopts
, which might be informative.
这篇关于如何在 Bash 中解析命令行参数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!