user654789384
user654789384

Reputation: 395

bash - passing optional arguments to script - parametername + string_value

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?

Upvotes: 1

Views: 3088

Answers (2)

dash-o
dash-o

Reputation: 14491

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

Upvotes: 1

John Kugelman
John Kugelman

Reputation: 362147

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: $@"

Upvotes: 2

Related Questions