Dynamic shell variables

Redowan Delowar January 11, 2025
Source

I came across a weird shell syntax today - dynamic shell variables. It lets you dynamically construct and access variable names in Bash scripts, which I haven't encountered in any of the mainstream languages I juggle for work.

In an actual programming language, you'd usually use a hashmap to achieve the same effect, but directly templating variable names is a quirky shell feature that sometimes comes in handy.

A primer

Dynamic shell variables allow shell scripts to define and access variables based on runtime conditions. Variable indirection (${!var} syntax) lets you reference the value of a variable through another variable. This can be useful for managing environment-specific configurations and function dispatch mechanisms.

Here's an example:

Here, ${!var} resolves to the value of the variable config_path because var contains its name. This allows you to dynamically decide which variable to reference at runtime.

Context-aware environment management

A more practical use of dynamic shell variables is managing environment-specific configurations. This is particularly handy in scenarios where you have multiple environments like staging and prod, each with its own unique configuration settings.

Run the script with an environment as the argument:

Output for env="staging":

By passing the environment as an argument, you can switch between environments without duplicating configuration logic.

One gotcha to be aware of is that appending text directly to the ${!VAR} syntax (e.g., ${!env}_URL) doesn't produce the intended results. Instead of resolving staging_URL, this line will print only _URL:

Output:

This happens because ${!VAR} only resolves the value of VAR and doesn't support direct concatenation. To avoid this, construct the full variable name (URL="${env}_URL") before using ${!VAR} for indirect expansion. This ensures the correct variable is accessed.

Function dispatch

Another neat use case for dynamic variables is function dispatch - calling the appropriate function based on runtime conditions. This technique can be used to simplify scripts that need to handle multiple services or operations.

Run the script with service and operation as arguments:

This returns:

Similarly, running ./script.sh db status prints:

Temporary file handling

Dynamic variables can also help manage temporary files or logs in scripts that process multiple datasets. By dynamically generating variable names, you can track temporary file paths for each dataset without conflicts.

Running this prints the following:

Here, each dataset gets a unique temporary file, managed dynamically by the script. It eliminates the need for manually creating and tracking file names.

This works, but like everything else in shell scripts, it can quickly turn into a hairball if we're not careful. While the syntax is nifty, I find it a bit hard to read at times!

Discussion in the ATmosphere

Loading comments...