在Bash中处理具有多个参数的命令行选项 [英] Processing command line options with multiple arguments in Bash

查看:246
本文介绍了在Bash中处理具有多个参数的命令行选项的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在研究使用bash脚本处理命令行参数。我有多个可选参数,每个参数都有一个或多个操作数。一个示例是:

I have been researching on using bash scripts to process command-line arguments. I have multiple optional arguments, each of which have one or more operands. An example is:

./script.sh -f file1 file2 -s server1 server2

-f 本身是可选的,但必须后面跟文件名; -s 是可选的,可以不使用任何操作数或操作数来使用。

-f itself is optional, but must be followed by filename; -s is optional, can be used without any operands or operands.

我知道我可以强制放置在操作数上,因此我只处理一个操作数的参数,并且可以使用 case $ 1 $ 2 shift 进行处理。

I know I can force putting "" on operands so I only deal with arguments with one operand and can use case $1 $2 shift to process it.

但我对此感兴趣,但不使用引号,只是为用户节省了一些打字时间。

But I am interested in doing so without quotes, just to save some typing for the users.

一个粗略的主意将被读为 $ @ 作为一个字符串,并用空格隔开,然后用-/-定位参数,并在其后分配操作数。也许我可以使用数组来做到这一点?

A rough idea would be read in "$@" as one string, and separate them by space, then locate arguments with -/-- and assign operands following them. Maybe I can use an array to do that?

任何建议都将受到欢迎。

Any suggestions would be welcome.

推荐答案

感谢您的精彩建议。花了更多时间后,我决定采用以下解决方案:

Thanks folks for your wonderful suggestions. After spending some more time I resolved to the solution below:

简单地说,我使用 case 并进行少量检查确定参数是否为选项。我在参数处理期间仅使用alter flag变量,然后使用flags确定我将执行的功能。以某种方式,我可以选择不同顺序的选项。

Simply put, I use case and few checks to determine if the argument is an option or not. I use only alter flag variables during argument processing and then use the flags to determine what functions I will perform. In a way that I can have options in different order.


main(){

#标志,1为假,0为真。这是该死的bash LOCAL_DEPLOY = 1
SERVER_DEPLOY = 1 DRY_RUN = 0

main(){
# flags, 1 is false, 0 is true. it's the damn 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

}

这篇关于在Bash中处理具有多个参数的命令行选项的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆