文章目录
- 问题
- 回答
- 以空格分隔选项和参数
- 以等号分隔选项和参数
 
- 参考
 
问题
假设,我有一个脚本,它会被这样一行调用:
./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 ?
回答
以空格分隔选项和参数
样例程序如下:
cat >/tmp/demo-space-separated.sh <<'EOF'
#!/bin/bashPOSITIONAL_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 设置为 YESDEFAULT=YESshift # 跳过参数;;-*|--*)  #如果参数是以 - 或 -- 开头且未知的选项,打印错误信息并退出echo "Unknown option $1"exit 1;;*)  #对于所有其他非选项参数(即位置参数),将它们逐一添加到 POSITIONAL_ARGS 数组中,POSITIONAL_ARGS+=("$1") # 保存位置参数shift;;esac
doneset -- "${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 ]]; thenecho "The non option arguments are:" $@
fi
EOFchmod +x /tmp/demo-space-separated.sh/tmp/demo-space-separated.sh -e log -s /var/log pos1 pos2复制粘贴上述代码块的输出:

推荐用法:
demo-space-separated.sh -e log -s /var/log pos1
以等号分隔选项和参数
样例程序如下:
cat >/tmp/demo-equals-separated.sh <<'EOF'
#!/bin/bashfor 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=YESshift # 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 ]]; thenecho "The non option arguments are:" $@
fi
EOFchmod +x /tmp/demo-equals-separated.sh/tmp/demo-equals-separated.sh -e=log -s=/var/log pos3 pos4其中 ${i#*=} 用于删除参数 $i 从左边开始匹配的第一个 = 及其左边的所有字符。
复制粘贴上述代码块的输出:

推荐用法:
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
相关阅读:
- sh和Bash的区别
- 2>&1是什么意思
- 为什么我不能在脚本中使用“cd“来更改目录
- 为什么Bash中的“[“和“]“周围应该有空格
- 如何使用bash脚本并行运行多个程序
- 为什么要使用xargs命令