比如说,我有一个用这一行调用的脚本:
./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
?
最佳答案
Bash 空格分隔(例如 --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
复制粘贴上面 block 的输出
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
Bash 等号分隔(例如,--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
复制粘贴上面 block 的输出
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-equals-separated.sh -e=conf -s=/etc /etc/hosts
更好地理解${i#*=}
在 this guide 中搜索“删除子字符串” .它在功能上等同于 `sed 's/[^=]*=//' <<< "$i"`
调用不必要的子进程或 `echo "$i" | sed 's/[^=]*=//'`
这会调用两个 不必要的子进程。
将 bash 与 getopt[s] 一起使用
getopt(1) 限制(旧的,相对较新的 getopt
版本):
- 不能处理空字符串参数
- 无法处理带有嵌入空格的参数
最近getopt
版本没有这些限制。有关详细信息,请参阅这些 docs .
POSIX 获取选项
此外,POSIX shell 和其他提供 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
复制粘贴上面 block 的输出
verbose=1, output_file='/etc/hosts', Leftovers: foo bar
用法
demo-getopts.sh -vf /etc/hosts foo bar
getopts
的优点|是:
- 它更便携,并且可以在其他 shell 中工作,例如
dash
. - 它可以处理多个单个选项,例如
-vf filename
以典型的 Unix 方式自动进行。
getopts
的缺点是它只能处理短选项( -h
,而不是 --help
)而无需额外的代码。
有一个getopts tutorial这解释了所有语法和变量的含义。在 bash 中,还有 help getopts
,这可能会提供信息。
关于bash - 我如何在 Bash 中解析命令行参数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/192249/