2

I'm trying to create a Bash function that assigns a default value to unset variables. This is a simplified example of my non-working script:

#! /usr/bin/env bash

# My broken validation function
validate_input() {
  if [ -z "$1" ]; then
    set -- "default"
  fi
}

# Parse arguments
while [ "$#" -gt 0 ]; do
  case "$1" in
    --foo=*)
    foo="${1#*=}"
    ;;
    --bar=*)
    bar="${1#*=}"
    ;;
    *)
    printf '%s\n' "Invalid argument ($1)"
    exit 1
    ;;
  esac
  shift
done

# Validate foo and bar
validate_input "$foo"
validate_input "$bar"

# Print results
printf '%s\n' "foo: $foo"
printf '%s\n' "bar: $bar"

So, users can use the arguments --foo and --bar to set the variables $foo and $bar. The validate_input function checks if a variable is set, and if not it's supposed to assign it the value "default". It's the last bit that isn't working:

$ ./test --foo=hello
foo: hello
bar: 

The expected output is:

foo: hello
bar: default

I have read up on positional arguments and set but I'm a bit out of my comfort zone here.

2
  • Try to send name of variable, not the content: validate_input "foo" Apr 4, 2022 at 20:19
  • @RomeoNinov - that was what I initially tried. However, in that case "foo" and "bar" are always set.
    – rkhff
    Apr 4, 2022 at 20:46

1 Answer 1

6

Changing the positional parameters in the function have no affect on the variables, as you've seen. Some alternative implementations:

using parameter substitution:

# Validate foo and bar
foo=${foo:-"default"}
bar=${bar:-"default"}

using a different parameter substitution with the : colon command.

# Validate foo and bar
: ${foo:="default"} ${bar:="default"}

Using a function that uses a nameref (requires bash version 4.3 or higher)

validate_input() {
  local -n var=$1
  [[ -z $var ]] && var=default
}

# Validate foo and bar
validate_input foo
validate_input bar

Another way to do this is to set the default values before parsing the arguments.

foo=default
bar=default

# Parse arguments
while [ "$#" -gt 0 ]; do
...
done

# Print results
printf 'foo: %s\n' "$foo"
printf 'bar: %s\n' "$bar"
1
  • Ah! I had been looking at foo=${foo:-"default"} but didn't realise I could use that instead of the function - I tried to use it inside the function. It's working now, and I'm reading up on nameref.
    – rkhff
    Apr 4, 2022 at 21:55

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .