2

I'm using bash 4.4.19(1)-release.

At the start of my program I read customer configuration values from the command line, configuration file(s), and the environment (in decreasing order of precedence). I validate these configuration values against internal definitions, failing out if required values are missing or if the customer values don't match against accepted regular expressions. This approach is a hard requirement and I'm stuck using BASH for this.

The whole configuration process involves the parsing of several YAML files and takes about a second to complete. I'd like to only have to do this once in order to preserve performance. Upon completion, all of the configured values are placed in a global associative array declared as follows:

declare -gA CONFIG_VALUES

A basic helper function has been written for accessing this array:

# A wrapper for accessing the CONFIG_VALUES array.
function get_config_value {
    local key="${1^^}"
    local output
    output="${CONFIG_VALUES[${key}]}"
    echo "$output"
}

This works perfectly fine when all of the commands are run within the same shell. This even works when the get_config_value function is called from a child process. Where this breaks down is when it's called from a child process and the value in the array contains slashes. This leads to errors such as the following (line 156 is "output="${CONFIG_VALUES[${key}]}"):

config.sh: line 156: path/to/some/file: syntax error: operand expected (error token is "/to/some/file")

This is particularly obnoxious because it seems to be reading the value "path/to/some/file" just fine. It simply decides to announce a syntax error after doing so and falls over dead instead of echoing the value.

I've been trying to circumvent this by running the array lookup in a subshell, capturing the syntax failure, and grepping it for the value I need:

# A wrapper for accessing the CONFIG_VALUES array.
function get_config_value {
    local key="${1^^}"
    local output
    if output="$(echo "${CONFIG_VALUES[${key}]}" 2>&1)"; then
        echo "$output"
    else
        grep -oP "(?<=: ).*(?=: syntax error: operand expected)" <<< "$output"
    fi
}

Unfortunately, it seems that BASH won't let me ignore the "syntax error" like that. I'm not sure where to go from here (well... Python, but I don't get to make that decision).

Any ideas?

Alex Jansen
  • 1,455
  • 5
  • 18
  • 34
  • Which line is line 156? – Barmar Apr 15 '19 at 23:48
  • output="$CONFIG_VALUES[${key}]" – Alex Jansen Apr 16 '19 at 00:00
  • Is `path/to/some/file` the value of the config variable? – Barmar Apr 16 '19 at 00:10
  • How is this being run from a child shell? Are you exporting `CONFIG_VALUES`? – Barmar Apr 16 '19 at 00:11
  • I don't think you can export array variables. – Barmar Apr 16 '19 at 00:14
  • You realize `$CONFIG_VALUES[$key]` is incorrect? You're missing the braces: `${CONFIG_VALUES[$key]}` -- that being said, I don't see anything here that would produce that error – glenn jackman Apr 16 '19 at 00:59
  • @glennjackman thanks, my mistake. That was a copy+paste error when creating the question. I've fixed it. – Alex Jansen Apr 16 '19 at 01:01
  • @Barmar yes, "path/to/some/file" is an example value of one of the variables in the CONFIG_VALUES array. I'm not exporting CONFIG_VALUES anywhere. By declaring it as global "-g" I'm usually able to access it from subshells. – Alex Jansen Apr 16 '19 at 01:06
  • I have a sinking suspicion that I need to abandon the associative array and export every single value individually. – Alex Jansen Apr 16 '19 at 01:08
  • The question says child processes, not subshells, that's why I was confused. – Barmar Apr 16 '19 at 01:16
  • 1
    Can you create a [mcve] that demonstrates the problem? – Barmar Apr 16 '19 at 01:16
  • I spent a couple of hours trying to reproduce the exact issue, but it was a bit too complicated to whittle down. The script in question is being called from a Makefile which launches a BASH script which runs find + exec to launch the BATS testing framework which launches another shell script which sources another BASH script which sources another BASH script which executes another BASH script which sources this script. The array is set in the original test script and read from this one. – Alex Jansen Apr 18 '19 at 02:33
  • I'm voting to close my question as "unclear". I believe the general takeaway is: "Don't count on associative arrays to work properly in child processes". – Alex Jansen Apr 18 '19 at 02:40

0 Answers0