How can I conditionally pass an argument from a POSIX shell script?

Modifying your original script:

#!/bin/sh
echo "Noise $1"
echo "Enhancement $2"
for snr in 0 5 10 15 20 25
do
  python evaluate.py --noise "$1" --snr "$snr" --iterations 1250 ${2:+--enhancement "$2"}
done

The standard parameter expansion ${var:+word} will expand to word if the variable var is set and not empty. In the code above, we use it to add --enhancement "$2" to the command if $2 is available and not empty.

I've also taken the liberty to assume that what you are giving to --snr as an option-argument should be the loop variable's value.


My personal touch on the code (mostly just using printf rather than echo, avoiding long lines, and giving the code a bit more air):

#!/bin/sh

printf 'Noise %s\n' "$1"
printf 'Enhancement %s\n' "$2"

for snr in 0 5 10 15 20 25; do
    python evaluate.py \
        --noise "$1" \
        --snr "$snr" \
        --iterations 1250 \
        ${2:+--enhancement "$2"}
done

As mosvy points out in comments below: If your /bin/sh happens to be the dash shell, or some other shell that does not properly reset IFS as a new shell session starts (this is required by POSIX), and if you have, for one reason or other, exported IFS and given it a non-default value, then you may want to use unset IFS at the top of the above script.

Do that whenever you have fixed all other issues that exporting IFS doubtlessly have raised (don't export IFS).


On a minimal POSIX shell, that does not support any arrays, you can just manipulate the positional argument list with set command. Just before the for loop you can do

if [ -z "$2" ]; then
    set -- --noise "$1" --snr 25 --iterations 1250
else
    set -- --noise "$1" --snr 25 --iterations 1250 --enhancement "$2"
fi

and now run your for loop as

for snr in 0 5 10 15 20 25; do
    python evaluate.py "$@"
done

If your shell supports array bourne again shell bash, zsh or other, you can just use an array

argv=(--noise "$1" --snr 25 --iterations 1250)

if [ ! -z "$2" ]; then
    argv+=( --enhancement "$2" )
fi

and now call the script as

python evaluate.py "${argv[@]}"

As pointed in the comments, you are not using the actual value of snr value from the for loop. Use the value as $snr where applicable in the script arguments, in which case you might need to move the logic of constructing the argument list inside the loop.


Build the argument in a variable based on the input:

#!/bin/sh
echo "Noise $1"
echo "Enhancement $2"

if [ $# -eq 1 ]
then
   enhance=""
else
   enhance="--enhancement $2"
fi

for snr in 0 5 10 15 20 25
do
  python evaluate.py --noise $1 --snr "$snr" --iterations 1250 $enhance
done

(Also includes the correction of the loop variable in the body of the loop)