在 bash 脚本中解析参数的最佳方法
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/19146250/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Best way to parse arguments in bash script
提问by sicklybeans
So I've been reading around about getopts, getopt, etc. but I haven't found an exact solution to my problem.
所以我一直在阅读有关 getopts、getopt 等的信息,但我还没有找到解决我的问题的确切方法。
The basic idea of the usage of my script is:
我的脚本使用的基本思路是:
./program [-u] [-s] [-d] <TEXT>
Except TEXT is not required if -d is passed. Note that TEXT is usually a paragraph of text.
如果通过 -d,则不需要 TEXT。请注意,TEXT 通常是一段文本。
My main problem is that once getopts finishing parsing the flags, I have no way of knowing the position of the TEXT parameter. I could just assume that TEXT is the last argument, however, if a user messes up and does something like:
我的主要问题是,一旦 getopts 完成对标志的解析,我就无法知道 TEXT 参数的位置。我可以假设 TEXT 是最后一个参数,但是,如果用户搞砸并执行以下操作:
./program -u "sentence 1" "sentence 2"
then the program will not realize that the usage is incorrect.
那么程序就不会意识到用法是不正确的。
The closest I've come is using getopt and IFS by doing
我最接近的是使用 getopt 和 IFS
ARGS=$(getopt usd: $*)
IFS=' ' read -a array <<< "$ARGS"
The only problem is that TEXT might be a long paragraph of text and this method splits every word of text because of the spaces.
唯一的问题是 TEXT 可能是一段很长的文本,并且由于空格,此方法会拆分文本的每个单词。
I'm thinking my best bet is to use a regular expression to ensure the usage is correctly formed and then extract the arguments with getopts, but it would be nice if there was a simpler solution
我认为我最好的选择是使用正则表达式来确保正确形成用法,然后使用 getopts 提取参数,但如果有更简单的解决方案就好了
回答by rici
It's quite simple with getopts
:
这很简单getopts
:
#!/bin/bash
u_set=0
s_set=0
d_set=0
while getopts usd OPT; do
case "$OPT" in
u) u_set=1;;
s) s_set=1;;
d) d_set=1;;
*) # getopts produces error
exit 1;;
esac
done
if ((!d_set && OPTIND>$#)); then
echo You must provide text or use -d >>/dev/stderr
exit 1
fi
# The easiest way to get rid of the processed options:
shift $((OPTIND-1))
# This will run all of the remaining arguments together with spaces between them:
TEXT="$*"
回答by evan
This is what I typically do:
这是我通常的做法:
local badflag=""
local aflag=""
local bflag=""
local cflag=""
local dflag=""
while [[ "" == -* ]]; do
case in
-a)
aflag="-a"
;;
-b)
bflag="-b"
;;
-c)
cflag="-c"
;;
-d)
dflag="-d"
;;
*)
badflag=
;;
esac
shift
done
if [ "$badflag" != "" ]; do
echo "ERROR CONDITION"
fi
if [ "" == "" ] && [ "$dflag" == "" ]; do
echo "ERROR CONDITION"
fi
local remaining_text=$@