问题:
假设,我有一个脚本,它会被这样一行调用:
代码语言:javascript复制./myscript -vfd ./foo/bar/someFile -o /fizz/someOtherFile
或者这个:
代码语言:javascript复制./myscript -v -f -d -o /fizz/someOtherFile ./foo/bar/someFile
如何解析 v、f 和 d,使它们都被设置为 true,并且 outFile 等于 /fizz/someOtherFile ?
回答:
以空格分隔选项和参数
样例程序如下:
代码语言:javascript复制cat >/tmp/demo-space-separated.sh <<'EOF'
#!/bin/bash
POSITIONAL_ARGS=() #初始化一个空数组,用来存储位置参数
while [[ $# -gt 0 ]]; do #当命令行参数的数量大于0时,进入循环
case $1 in
-e|--extension) #如果参数是这个,脚本会将紧随其后的参数(文件扩展名)保存在变量 EXTENSION 中
EXTENSION="$2"
shift # 跳过参数
shift # 跳过后面的值
;;
-s|--searchpath) #如果参数是这个,脚本会将紧随其后的参数(搜索路径)保存在变量 SEARCHPATH 中
SEARCHPATH="$2"
shift # 跳过参数
shift # 跳过后面的值
;;
--default) #如果参数是这个,脚本会将变量 DEFAULT 设置为 YES
DEFAULT=YES
shift # 跳过参数
;;
-*|--*) #如果参数是以 - 或 -- 开头且未知的选项,打印错误信息并退出
echo "Unknown option $1"
exit 1
;;
*) #对于所有其他非选项参数(即位置参数),将它们逐一添加到 POSITIONAL_ARGS 数组中,
POSITIONAL_ARGS =("$1") # 保存位置参数
shift
;;
esac
done
set -- "${POSITIONAL_ARGS[@]}" # 将数组里的参数设置为当前 shell 的位置参数
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 "The non option arguments are:" $@
fi
EOF
chmod x /tmp/demo-space-separated.sh
/tmp/demo-space-separated.sh -e log -s /var/log pos1 pos2
复制粘贴上述代码块的输出:
推荐用法:
代码语言:javascript复制demo-space-separated.sh -e log -s /var/log pos1
以等号分隔选项和参数
样例程序如下:
代码语言:javascript复制cat >/tmp/demo-equals-separated.sh <<'EOF'
#!/bin/bash
for i in "$@"; do #循环遍历所有的命令行参数
case $i in
-e=*|--extension=*)
EXTENSION="${i#*=}" #使用 ${i#*=} 来提取等号 = 后面的值(即文件扩展名),并将其保存在变量 EXTENSION 中
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 #结束for循环
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 "The non option arguments are:" $@
fi
EOF
chmod x /tmp/demo-equals-separated.sh
/tmp/demo-equals-separated.sh -e=log -s=/var/log pos3 pos4
其中${i#*=}
用于删除参数$i
从左边开始匹配的第一个=
及其左边的所有字符。
复制粘贴上述代码块的输出:
推荐用法:
代码语言:javascript复制demo-equals-separated.sh -e=log -s=/var/log pos1 pos2
参考:
- stackoverflow question 192249
- https://www.gnu.org/software/bash/manual/bash.html#The-Set-Builtin
- https://www.gnu.org/software/bash/manual/bash.html#Shell-Parameter-Expansion