1

i use a script that accepts parameter. parameters are optional and may occur in any order.

#!/bin/bash
# script name: test.sh
for var in "$@"
do
    if [ ! -z "$var" ]   && ([ $var = "--example" ] || [ $var = "-e" ]); then
        echo "example"
    elif [ ! -z "$var" ]   && ([ $var = "--project" ] || [ $var = "-p" ]); then
        echo "project with string xxxxxxx"
    fi
done

in this simple example, you could call it like follows (some examples):

# this will echo example
./test.sh --example 
# this will echo project with string xxxxxxx
./test.sh --project
# this will echo both example and project with string xxxxxxx
./test.sh --example --project

NOW, what i want to achieve is that i can do something like this (warning, this is pseuco code):

#!/bin/bash
# script name: test.sh
for var in "$@"
do
    if [ ! -z "$var" ]   && ([ $var = "--example" ] || [ $var = "-e" ]); then
        echo "example"
    elif [ ! -z "$var" ]   && ([ $var = "--project" ] || [ $var = "-p" ]); then
        echo "project with string $VAR_VALUE"
    fi
done



# this will echo example
./test.sh --example 
# this will echo project with string myproject1
./test.sh --project="myproject1" 
# this will echo both example and project with string myproject2
./test.sh --example --project="myproject2"

can someone help me rewrite it so this will work somehow?

2 Answers 2

2

Use getopt. It handles short and long options, allows for both --long value and --long=value, decomposes -abc into -a -b -c, understands -- to end option parsing, and more.

#!/bin/bash

args=$(getopt -o ep: -l example,project: -n "$0" -- "$@") || exit
eval set -- "$args"

while [[ $1 != '--' ]]; do
    case "$1" in
        -e|--example) echo "example";      shift 1;;
        -p|--project) echo "project = $2"; shift 2;;

        # shouldn't happen unless we're missing a case
        *) echo "unhandled option: $1" >&2; exit 1;;
    esac
done
shift  # skip '--'

echo "remaining non-option arguments: $@"
Sign up to request clarification or add additional context in comments.

2 Comments

What does the getopt -n option do? I looked up the man page, but don't understand it.
@jrahhali If the user makes a mistake with the arguments getopt will print "progname: error message". -n tells it what "progname" is so it looks like the error message is coming from your program.
1

There are two possible path toward parsing argument list

  1. Build custom option parser
  2. use getopt, using 'long options'

The first approach is relatively simple (at this time). Using case instead of if to handle variants:

last_arg=
for arg in "$@"
do
    if [ "$last_arg" = "-p" ] ; then
        VAR_VALUE=$arg ;
        last_arg=
        echo "project with string $VAR_VALUE"
        continue
    fi
    case "$arg" in
        -e | --example)
            echo "example" ;;
        -p)
            last_arg=$arg ;;
        --project=*)
            VAR_VALUE=${arg#*=}
            echo "project with string $VAR_VALUE" ;;
        *) ERROR-MESSAGE ;;
    esac
done
exit

The BETTER approach is to leverage existing code. In particular getopt, which can handle long options:

#! /bin/bash
if T=$(getopt -o ep: --long 'example,project:' -n ${0#*/} -- "$@") ; then
        eval set -- "$T"
else
        exit $?
fi
while [ "$#" -gt 0 ] ; do
        case "$1" in
                -e | --example)
                        echo "example"
                        ;;
                -p | --project)
                        shift
                        VAR_VALUE=$1
                        echo "project with string $VAR_VALUE"
                        ;;
                --)
                        break
                        ;;
                *) echo "ERROR:$1" ;;
        esac
        shift
done

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.