0

I'm trying to use the input from a switch in multiple functions but the variable seems to be forgotten when moving to a different function called by a different switch

#! /bin/bash

function function1 {
echo $variable1
}

function function2 {
echo $variable1
}

while getopts "p:ah" arg; do
    case $arg in
        p) variable1="$OPTARG" function1 ;;
        a) function2 ;;
        h) usage ;;
        \?) usage ;;
    esac
done

Output:

./my-script.sh -p hello -a
hello

the second function doesn't echo the variable

  • Since `variable1="$OPTARG"` is a prefix to command (function call) `function1` rather than a separate command, it only applies within that command. – Gordon Davisson Aug 14 '22 at 21:01
  • @GordonDavisson yes I know. My question is how to make it a global variable – PenN256 Aug 14 '22 at 21:13
  • Make the assignment a separate command by putting a semicolon or line break between it and the function call; see ["Variable value doesn't change in bash script"](https://stackoverflow.com/questions/46978838/variable-value-doesnt-change-in-bash-script). BTW, you should also double-quote variable references (`echo "$variable1"` instead of `echo $variable1`), and it's usually best to just set variables in a `getopts` loop, then act on them (e.g. by calling functions setermined by those variables) *after* the loop. – Gordon Davisson Aug 14 '22 at 22:12
  • @GordonDavisson that worked! Thank you. What do you mean in a getopts loop? I need a way to run the functions in the order the scripts needs, not the order the switches are provided – PenN256 Aug 14 '22 at 22:38
  • @PenN256, your script shows the 2 functions in the getopt while statement. Better control can be had by having the the functions outside that loop, and limiting that loop to command parsing and option/variable settings for later logic control or usage. Later logic would then control the sequence of when any input would be handled, by simply coding that sequence. Most important, the full state of the command line conditions would have been parsed and assimilated by the program before proceeding with the function steps. – Eric Marceau Sep 15 '22 at 21:53

1 Answers1

0

Further to my comment, the following is an example of using getarg in a corporate production environment:

## initialize vars
   ouser="${USER:-`whoami`}"
   ohost="${HOST:-`hostname`}"

   set -- `getopt hHVu:n: ${*:-}`
   test $? -ne 0  &&  usage  &&  exit 9

   for i in $*; do
        case $i in
        -h)     usage 0  &&  exit 9                     ;;
        -H)     usage 1  &&  exit 9                     ;;
        -V)     echo "$P $rcsid"|cut -d' ' -f1,4-5; exit;;
        -u)     ouser=$2        ;  shift 2              ;;
        -n)     ohost=$2        ;  shift 2              ;;
        --)       shift         ;  break                ;;
        esac
   done

My own preference is to bypass getargs and parse the command line directly as shown in the following example (note that parameter strings could just as well be single-character, i.e. "-x", but can be a mix or short or long parameters):

useUID=0

cUID="-99"
cOwner=""
cGID="-99"
cGroup=""

Owner=""
Group=""

VERB=""
SAMPLE=0
FORCE=0
SHOW=1

while [ $# -gt 0 ]
do
    case $1 in
        --verbose ) VERB="-v" ; shift ;;
        --sample )   SAMPLE=1 ; shift ;;
        --force )     FORCE=1 ; shift ;;
        --nomatch )    SHOW=0 ; shift ;;
        --match )      SHOW=1 ; shift ;;

        --oUID )      cUID=$2 ; useUID=1 ; shift ; shift ;;
        --oUSR )    cOwner=$2 ; useUID=0 ; shift ; shift ;;
        --oGID )      cGID=$2 ; useGID=1 ; shift ; shift ;;
        --oGRP )    cGroup=$2 ; useGID=0 ; shift ; shift ;;

        --nUSR )     Owner=$2 ; shift ; shift ;;
        --nGRP )     Group=$2 ; shift ; shift ;;
    esac
done

or again as shown here:

ASSIGN=0
REPORT=0
VERB=0
SINGLE=0
USB=0
while [ $# -gt 0 ]
do
    case ${1} in
                --default ) REPORT=0 ; ASSIGN=0 ; shift ;;
                --report )  REPORT=1 ; ASSIGN=0 ; shift ;;
                --force )   REPORT=0 ; ASSIGN=1 ; shift ;;
                --verbose ) VERB=1 ; shift ;;
                --single )  SINGLE=1 ; shift ;;
                --usb )     USB=1 ; shift ;;
                * ) echo "\n\t Invalid parameter used on the command line.  Valid options:  [ --default | --report | --force | --single     | --usb | --verbose ] \n Bye!\n" ; exit 1 ;;
    esac
done

Many times, the variables set from the input parsing are strictly boolean settings for conditional testing before taking actions.

Eric Marceau
  • 1,601
  • 1
  • 8
  • 11