ClimateUnboxed
ClimateUnboxed

Reputation: 8087

Automatic parsing of getopts options into dynamic variables of same name in bash

I have a bash script I wrote with say, 3 command line options, bib, bob and boo... and I want to read in the user options into a bash variable of the same name, which I do as follows:

PARSED_OPTIONS=$(getopt -n $0  --long "bib:,bob:,boo:"  -- "$@")

eval set -- "$PARSED_OPTIONS";

while true; do
  case "$1" in

  --bib)
  bib=$2
  shift 2;;

  --bob)
  bob=$2
  shift 2;;

  --boo)
  boo=$2
  shift 2 ;;

  --)
  shift
  break;;

  esac
done

This all works fine, so far, so good...

But now I want to extend this to a list of many many options, and so rather than writing out a long case statement, it would be really nice to be able to somehow loop over a list of options and automatically pass the options to the variable, something along these lines

opts="bib:,bob:,boo:," 

PARSED_OPTIONS=$(getopt -n $0  --long $opts -- "$@")

for arg in `echo $opts | tr , " "` ; do 
  eval set -- "$PARSED_OPTIONS";
  while true; do

    case "$1" in
      --${arg})
      declare $arg=$2
      shift 2
      ;;
      --)
      shift
      break;;
    esac
  done
done

I'm using the declaration statement to get the argument into a dynamic variable of the same name (see Dynamic variable names in Bash second solution), and this solution to do the loop over comma separated lists Loop through a comma-separated shell variable but I'm getting an infinite loop here. I think because the 2 unused options are allows as they are in the PARSED_OPTIONS list, but then they are not sliced off in the loop as only "arg" is looked for... I can't see an obvious way around this, but I'm sure there is one.

Upvotes: 1

Views: 880

Answers (1)

ClimateUnboxed
ClimateUnboxed

Reputation: 8087

I realized that I had the shift command still inside the case statement, so that is why it wasn't exiting. I also needed to strip the colon : from the argument, so here is my automated argument retrieval for a bash script that works:

# specify an arbitrary list of arguments:

opts=bib:,bob:,boo:

PARSED_OPTIONS=$(getopt -n $0  --long "${opts}"  -- "$@")

for arg in ${opts//,/ } ; do 
  var=${arg//:} # remove the colon
  eval set -- "$PARSED_OPTIONS";
  while true ; do
    case "$1" in
      --${var})
      declare ${var}=$2
      ;;
    --)
      break
      ;;
    esac
    shift 2
  done
done

So if you try test_script --boo 3 --bib hello --bob lkkfrfrfr

echo $bib $bob $boo

should give

hello lkkfrfrfr 3

Upvotes: 1

Related Questions