How to check for 3 optional parameter in shell

In my script I have 3 mandatory parameters , host (-s), key(-k) ,prop_name(-p) but I have two conditions , either one would be entered by the user while running the script

  1. prop_val(-v) - optional parameter
    $0 -s host -k 5000 -p 'Point' -v '21'

  2. begin_val(-b) & end_val(-e) - optional parameter
    $0 -s host -k 7087 -p 'Point2' -b '12' -e '18'

How to check these either of the optional parameter(-v or (-b&-e) are present while running the script other throw error

Part of Script:

host=
key=
prop_name=
prop_val=
begin_val=
end_val=

while getopts "s:k:p:b:v:e:h:" optchar ; do
    case $optchar in
    s)  host=$OPTARG ;;
    k)  key=$OPTARG ;;
    p)  prop_name=$OPTARG ;;
    v)  prop_val=$OPTARG ;;
	b)  begin_val=$OPTARG ;;
	e)  end_val=$OPTARG ;;
	h)  usage
       exit 1
	esac
	
done

if [ -z "${host}" ]||[ -z "${key}" ]||[ -z "${prop_name}" ] 
then
    usage
    exit 1
fi

.....
.....
....

Please help in the if else condition

Hi @pragyakpr33,

Welcome to the forum! :blush:

Just a quick reminder: per the forum rules, please format your code using markdown for clarity.

You can find links to the forum rules and a handy Markdown Cheat Sheet at the top of the main page for reference:

Looking forward to seeing your contributions!

1 Like

one approach:

  • validate all args
  • throw error if any of the mandatory (-s -k -p) are missing
  • if -v is present
    • throw error if either -b or -e are present
  • else test that -b AND -e are present, otherwise throw an error

The shell can use the { command; command; } grouping to form a long if clause:

if
  [ -z "$host" ] || [ -z "$key" ] || [ -z "$prop_name" ] || {
    [ -z "$prop_val" ] && {
      [ -z "$begin_val" ] || [ -z "$end_val" ]
    }
  }
then
  usage
  exit 1
fi

Note that a ( command; command ) grouping would work but would enforce a sub shell: extra fork() overhead, and modified parameters cannot be retrieved in the main shell.

For covering "if -v is present then throw error if either -b or -e are present" this scheme extends to

if
  [ -z "$host" ] || [ -z "$key" ] || [ -z "$prop_name" ] || {
    [ -z "$prop_val" ] && {
      [ -z "$begin_val" ] || [ -z "$end_val" ]
    }
  } || {
    [ -n "$prop_val" ] && {
      [ -n "$begin_val" ] || [ -n "$end_val" ]
    }
  }
then

where the prop_val is queried twice. It is smarter to use an if-else-fi where the last condition (in the body) determines the resulting status:

if
  [ -z "$host" ] || [ -z "$key" ] || [ -z "$prop_name" ] || {
    if [ -z "$prop_val" ]
    then
      [ -z "$begin_val" ] || [ -z "$end_val" ]
    else
      [ -n "$begin_val" ] || [ -n "$end_val" ]
    fi
  }
then

Last but not least, if you have a usage function, then you can call it at different points, and add individual messages:

if  [ -z "$host" ]; then
  echo "missing -s host"
  usage; exit 1
fi
if [ -z "$key" ]; then
  echo "missing -k key"
  usage; exit 1
fi
if [ -z "$prop_name" ]; then
  echo "missing -p prop_name"
  usage; exit 1
fi
if [ -z "$prop_val" ]; then
  if [-z "$begin_val" ] || [ -z "$end_val" ]; then
    echo "need both -b begin_val and -e end_val"
    usage; exit 1
  fi
else
  if [ -n "$begin_val" ] || [ -n "$end_val" ]; then
    echo "either -v prop_val or -b begin_val and -e end_val"
    usage; exit 1
  fi
fi
2 Likes

Thanks it worked for me.