我一直在研究使用bash脚本处理命令行参数。我有多个可选参数,每个参数都有一个或多个操作数。一个例子是:
./script.sh -f file1 file2 -s server1 server2
-f
本身是可选的,但必须后跟文件名; -s
是可选的,可以在没有任何操作数或操作数的情况下使用。
我知道我可以强制将“”放在操作数上,所以我只处理带有一个操作数的参数,并且可以使用case $1 $2 shfit
来处理它。
但是我有兴趣这样做没有引号,只是为了为用户节省一些打字。
粗略的想法将在"$@"
中作为一个字符串读取,并按空格分隔,然后使用-/--
定位参数并在其后面分配操作数。也许我可以使用数组来做到这一点?
欢迎任何建议。
答案 0 :(得分:1)
感谢大家提出的精彩建议。花了一些时间后,我决定采用下面的解决方案:
简单地说,我使用case
和几个检查来确定参数是否是一个选项。我在参数处理期间只使用alter flag变量,然后使用flags来确定我将执行的函数。在某种程度上,我可以选择不同的顺序。
的main(){
#flags,1为false,0为true。该死的bash LOCAL_DEPLOY = 1 SERVER_DEPLOY = 1 DRY_RUN = 0
FILES=("${ALLOWEDFILES[@]}");
DEPLOYTARGET=("${ALLOWEDSERVERS[@]}");
if [ $# -eq 0 ]
then
printf -- "Missing optins, perform DRY RUN\nFor help, run with -h/--help\n"
for target in "${FILES[@]}"; do generate "$target"; done
echo "....dry run: markdown files generated in rendered/"
exit 0
fi
while true ; do
case "$1" in
-f |--file) # required operands
case "$2" in
"") die $1 ;;
*)
FILES=($2)
for i in "${FILES[@]}"; do
if is_option $i; then die $1; fi # check for option
if ! check_allowed $i ${ALLOWEDFILES[@]}; then exit 1; fi
done;
shift 2;; # input FILES are good
esac ;;
-l|--local) # no operands expected
DRY_RUN=1 # turn off dryrun
LOCAL_DEPLOY=0 # turn on local deploy
shift ;;
-s|--server) # optional operands
case "$2" in
"") shift ;;
*)
DEPLOYTARGET=($2) # use input
for i in "${DEPLOYTARGET[@]}"; do
if is_option $i; then die $1; fi # check for option
if ! check_allowed $i ${ALLOWEDSERVERS[@]}; then exit 1; fi
done ; shift 2;; # use input value
esac
DRY_RUN=1
SERVER_DEPLOY=0
;;
-n|--dryrun) # dry-run:generate markdown files only
DRY_RUN=0
shift ;;
-h|--help) # docs
print_help
exit 0
;;
--) shift; break ;;
-?*)
printf 'ERROR: Unkown option: %s\nExisting\n\n' "$1" >&2
print_help
exit 1
shift
;;
*)
break ;;
esac
done
echo "choose files: ${FILES[@]}"
echo ""
# dry-run
if [ $DRY_RUN == 0 ]; then
echo "..perform dry run.."
for target in "${FILES[@]}"; do generate "$target"; done
echo "....dry run: markdown files generated in rendered/"
exit 0
fi
# local-deploy
if [ $LOCAL_DEPLOY == 0 ] && [ $SERVER_DEPLOY != 0 ]; then
echo "..deploy locally"
for target in "${FILES[@]}"; do
generate "$target" > /dev/null
deploylocal "$target"
done;
# sync hexo-gcs hexo-yby
cd "$(dirname $HEXOLOCATION)"
./syncRepo.sh
printf -- "....hexo-gcs hexo-yby synced\n"
cd $CURRENTLOCATION
fi
# server-deploy
if [ $SERVER_DEPLOY == 0 ]; then
echo "..deploy on servers: ${DEPLOYTARGET[@]}"
echo ""
for target in "${FILES[@]}"; do # deploy locally
generate "$target" > /dev/null
deploylocal "$target"
done
# sync hexo-gcs hexo-yby
cd "$(dirname $HEXOLOCATION)"
./syncRepo.sh
printf -- "....hexo-gcs hexo-yby synced\n"
cd $CURRENTLOCATION
# deploy to selected server: git or gcp
for dt in "${DEPLOYTARGET[@]}"; do
deployserver $dt
done
fi
}