Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Read a config file in BASH without using "source"

I'm attempting to read a config file that is formatted as follows:

USER = username
TARGET = arrows

I realize that if I got rid of the spaces, I could simply source the config file, but for security reasons I'm trying to avoid that. I know there is a way to read the config file line by line. I think the process is something like:

  1. Read lines into an array
  2. Filter out all of the lines that start with #
  3. search for the variable names in the array

After that I'm lost. Any and all help would be greatly appreciated. I've tried something like this with no success:

backup2.config>cat ~/1

grep '^[^#].*' | while read one two;do
    echo $two
done

I pulled that from a forum post I found, just not sure how to modify it to fit my needs since I'm so new to shell scripting.

http://www.linuxquestions.org/questions/programming-9/bash-shell-program-read-a-configuration-file-276852/


Would it be possible to automatically assign a variable by looping through both arrays?

for (( i = 0 ; i < ${#VALUE[@]} ; i++ ))
do
    "${NAME[i]}"=VALUE[i]           
done
echo $USER

Such that calling $USER would output "username"? The above code isn't working but I know the solution is something similar to that.

like image 223
Gerry Avatar asked Dec 14 '10 00:12

Gerry


2 Answers

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/bash

i=0
while read line; do
  if [[ "$line" =~ ^[^#]*= ]]; then
    name[i]=${line%% =*}
    value[i]=${line#*= }
    ((i++))
  fi
done < vars

echo "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 vars
sdf
USER = username
TARGET = arrows
asdf
as23

Output

$ ./varscript
total array elements: 2
name[0]: USER
value[0]: username
name[1]: TARGET
value[1]: arrows
name array: USER TARGET
value array: username arrows
like image 166
SiegeX Avatar answered Oct 29 '22 01:10

SiegeX


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/bash
configfile="/path/to/file"
shopt -s extglob
while IFS='= ' read lhs rhs
do
    if [[ $lhs != *( )#* ]]
    then
        # you can test for variables to accept or other conditions here
        declare $lhs=$rhs
    fi
done < "$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 keys
user=USER
target=TARGET
# access values
echo "Username: ${settings[$user]}, Target: ${settings[$target]}"

would output

Username: username, Target: arrows

like image 20
Dennis Williamson Avatar answered Oct 28 '22 23:10

Dennis Williamson