Read a config file in BASH without using "source" Read a config file in BASH without using "source" bash bash

Read a config file in BASH without using "source"


The following script iterates over each line in your input file (vars in my case) and does a pattern match against =. If the equal sign is found it will use Parameter Expansion to parse out the variable name from the value. It then stores each part in it's own array, name and value respectively.

#!/bin/bashi=0while read line; do  if [[ "$line" =~ ^[^#]*= ]]; then    name[i]=${line%% =*}    value[i]=${line#*= }    ((i++))  fidone < varsecho "total array elements: ${#name[@]}"echo "name[0]: ${name[0]}"echo "value[0]: ${value[0]}"echo "name[1]: ${name[1]}"echo "value[1]: ${value[1]}"echo "name array: ${name[@]}"echo "value array: ${value[@]}"

Input

$ cat varssdfUSER = usernameTARGET = arrowsasdfas23

Output

$ ./varscripttotal array elements: 2name[0]: USERvalue[0]: usernamename[1]: TARGETvalue[1]: arrowsname array: USER TARGETvalue array: username arrows


First, USER is a shell environment variable, so it might be better if you used something else. Using lowercase or mixed case variable names is a way to avoid name collisions.

#!/bin/bashconfigfile="/path/to/file"shopt -s extglobwhile IFS='= ' read lhs rhsdo    if [[ $lhs != *( )#* ]]    then        # you can test for variables to accept or other conditions here        declare $lhs=$rhs    fidone < "$configfile"

This sets the vars in your file to the value associated with it.

echo "Username: $USER, Target: $TARGET"

would output

Username: username, Target: arrows

Another way to do this using keys and values is with an associative array:

Add this line before the while loop:

declare -A settings

Remove the declare line inside the while loop and replace it with:

    settings[$lhs]=$rhs

Then:

# set keysuser=USERtarget=TARGET# access valuesecho "Username: ${settings[$user]}, Target: ${settings[$target]}"

would output

Username: username, Target: arrows


I have a script which only takes a very limited number of settings, and processes them one at a time, so I've adapted SiegeX's answer to whitelist the settings I care about and act on them as it comes to them.

I've also removed the requirement for spaces around the = in favour of ignoring any that exist using the trim function from another answer.

function trim(){    local var=$1;    var="${var#"${var%%[![:space:]]*}"}";   # remove leading whitespace characters    var="${var%"${var##*[![:space:]]}"}";   # remove trailing whitespace characters    echo -n "$var";}while read line; do    if [[ "$line" =~ ^[^#]*= ]]; then        setting_name=$(trim "${line%%=*}");        setting_value=$(trim "${line#*=}");        case "$setting_name" in            max_foos)                prune_foos $setting_value;            ;;            max_bars)                prune_bars $setting_value;            ;;            *)                echo "Unrecognised setting: $setting_name";            ;;        esac;    fidone <"$config_file";