anew10
anew10

Reputation: 299

is it possible to accept multiple parameters in an positional argument and also is there a way not to pass empty "" for arguments

Trying to run a python script via bash/shell script, figuring out what's the best way to accept multiple parameters in an argument and loop through all the parameters in $5 to run the same command on each of the address in $5. Also, is there a way not to pass in empty parameters while running the shell script? Below is what I worked on so far but confused on special parameters concept to use here https://www.gnu.org/software/bash/manual/html_node/Special-Parameters.html

#!/bin/bash

# Arguments
echo "Service: $1"
echo "Action: $2"
echo "file: $3"
echo "DockerV: $4"
echo "Address: $5"

python /scripts/service.py -s "$1" -t "$2" "$5"

Running it this way works, but only if empty quotes are passed in---
/users/shellScripts/serviceTest.sh "ALL" "Stop" " " " " "11.45.26.13"

Running it this way does not works, as $5 has more than 1 argument---
/users/shellScripts/serviceTest.sh "ALL" "Stop" " " " " "11.45.26.13 11.45.26.14 11.45.26.15"

I tried the script I wrote above but confused on the concept of special parameters of bash/shell. Expecting to execute the shell script without empty parameters(maybe setting them as optional) also having the ability to pass in multiple parameters into an argument and loop through all the parameters in $5 to run the same command on each of the address in $5.

Upvotes: 0

Views: 406

Answers (3)

Ed Morton
Ed Morton

Reputation: 203684

If you ever get stuck in a situation where the leading args might be missing, you can always populate your variables starting from the end instead of the beginning:

$ cat tst.sh
#!/usr/bin/env bash

v1first=$1
v1second=$2
v1third=$3

echo "v1first=$v1first"
echo "v1second=$v1second"
echo "v1third=$v1third"

echo '-------------'

n="$#"
((   n )) && v2third="${!n}"
(( --n )) && v2second="${!n}"
(( --n )) && v2first="${!n}"

echo "v2first=$v2first"
echo "v2second=$v2second"
echo "v2third=$v2third"

$ ./tst.sh the dog ran
v1first=the
v1second=dog
v1third=ran
-------------
v2first=the
v2second=dog
v2third=ran

$ ./tst.sh dog ran
v1first=dog
v1second=ran
v1third=
-------------
v2first=
v2second=dog
v2third=ran

Upvotes: 0

tjm3772
tjm3772

Reputation: 3154

Truly optional position arguments are very hard in general and likely impossible in your specific case, but you can use an options parser like getopts.

#!/bin/bash
args=()
while getopts ':s:t:' opt ; do
  case $opt in
    s) args+=( -s "$OPTARG" ) ;;
    t) args+=( -t "$OPTARG" ) ;;
    ?) echo "Invalid option $OPTARG" ;;
    :) echo "Option $OPTARG needs an argument" ;;
  esac
done
shift $(( OPTIND - 1 ))

for ip in "$@" ; do
  python /scripts/service.py "${args[@]}" "$ip"
done

Example invocation:

/users/shellScripts/serviceTest.sh -s "ALL" -t "Stop" 11.45.26.13 11.45.26.14 11.45.26.15

Important things to note:

  • getopts will help you handle all the optional content.
  • The options get built into an array to help pass them to the python script - see BashFAQ/50 for an in-depth explanation of why.
  • After getopts is done, shift is invoked to throw the options out so you're left with only the positional arguments. You can then iterate them with for ip in "$@".
  • Don't shove all of the positional arguments into quotes. It's easier to do something with each of them individually if you pass them to the script as separate arguments than if you pass them as one argument that the script then has to deconstruct.

Upvotes: 1

John Bollinger
John Bollinger

Reputation: 180351

what's the best way to accept multiple parameters in an argument

The best way is to use separate parameters instead of packing multiple logically distinct values into one.

If you have to work with multiple logically distinct values packed into a single parameter then there is a variety of ways to split them up. In your case, it looks like you are delimiting the values via whitespace, and that they cannot contain internal whitespace. In that event, you can use shell word splitting to split them apart.

loop through all the parameters in $5

The shell has a for loop, which you, under the circumstances, might use like so:

# intentionally omitting quotes around $5 on the next line:
for addr in $5; do
  python /scripts/service.py -s "$1" -t "$2" "$addr"
done

But if you instead pass all the addresses as separate arguments, then you could instead do this:

service=$1
action=$2
file=$3
docker_v=$4

shift 4

for addr in "$@"; do
  python /scripts/service.py -s "$service" -t "$action" "$addr"
done

is there a way not to pass in empty parameters while running the shell script?

Not when the script is using position to assign significance to its arguments, and there are required arguments following the optional ones.

It would be more idiomatic for a script with a large number of arguments or with any optional arguments to use flags (such as the -s and -t in your python command) to recognize the significance of its arguments. Especially of optional arguments. But argument processing would make your script much more complex, so if this does not need to be production quality then maybe you should consider just living with the empty arguments.

And speaking of empty arguments, "" and '' are empty. " " is not empty -- it represents a space character.

Upvotes: 1

Related Questions