文章目录
- 问题
- 回答
- 以空格分隔选项和参数
- 以等号分隔选项和参数
- 参考
问题
假设,我有一个脚本,它会被这样一行调用:
./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命令