14

I need to write a bash script, and would like it to parse unordered parameters of the format:

scriptname --param1 <string> --param2 <string> --param3 <date>

Is there a simple way to accomplish this, or am I pretty much stuck with $1, $2, $3?

0

5 Answers 5

10

You want getopts.

Sign up to request clarification or add additional context in comments.

3 Comments

getopts doesn't support long switches (starting with --). getopt does, but it is pretty horrible to use/read
Good point - if long switches are a must-have, getopts isn't the right tool.
This answer would be better with content and or example, instead of just a link.
8
while [[ $1 = -* ]]; do
    arg=$1; shift           # shift the found arg away.

    case $arg in
        --foo)
            do_foo "$1"
            shift           # foo takes an arg, needs an extra shift
            ;;
        --bar)
            do_bar          # bar takes no arg, doesn't need an extra shift
            ;;
    esac
done

2 Comments

Shouldn't do_foo "$2" be do_foo "$1"?
@xx77aBs yes, it should!
2

A nice example of how to implement short & long switches side by side is mcurl:

http://www.goforlinux.de/scripts/mcurl/

Comments

1

Bash has a getops function, as mentioned here before, that might solve your problems.

If you need anything more sophisticated, bash also supports positional parameters (ordered $1 ... $9, and then ${10} .... ${n}), you'll have to come up with your own logic to handle this input. One easy way to go is to put a switch/case inside of a for loop, iterating over the parameters. You can use either one of the two special bash vars that handle the input: $* or $@.

Comments

-1
#!/bin/bash

# Parse the command-line arguments
while [ "$#" -gt "0" ]; do
  case "$1" in
    -p1|--param1)
      PARAM1="$2"
      shift 2
    ;;
    -p2|--param2)
      PARAM2="$2"
      shift 2
    ;;
    -p3|--param3)
      PARAM3="$2"
      shift 2
    ;;
    -*|--*)
      # Unknown option found
      echo "Unknown option $1."

      exit 1
    ;;  
    *)
      CMD="$1"
      break
    ;;
  esac
done 


echo "param1: $PARAM1, param2: $PARAM2, param3: $PARAM3, cmd: $CMD"

When I execute this:

./<my-script> --param2 my-param-2 --param1 myparam1 --param3 param-3 my-command

it outputs what you expect:

param1: myparam1, param2: my-param-2, param3: param-3, cmd: my-command

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.