Processing command line options with multiple arguments in Bash [duplicate]

半世苍凉 提交于 2020-01-02 07:15:36

问题


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 itself is optional, but must be followed by filename; -s is optional, can be used without any operands or operands.

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.


回答1:


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

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(){
# 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

}



来源:https://stackoverflow.com/questions/46394825/processing-command-line-options-with-multiple-arguments-in-bash

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!