How to Read Config Files with Section in Bash Shell

How to read config files with section in bash shell

To use --exclude-from you will have to isolate the relevant section of the config into a temporary file. This is easy to do with a bit of sed:

sed -n '1,/rsync_exclude/d;/\[/,$d;/^$/d;p' config.file > $tmp_file
rsync -avz --exclude-from $tmp_file source/ destination/

I am omitting error checking and cleanup for clarity.

Note that rsync can read the exclude pattern from the stdin for an - input, so this is even shorter:

sed -n '1,/rsync_exclude/d;/\[/,$d;/^$/d;p' config.file | \
rsync -avz --exclude-from - source/ destination/


  • The 1,/rsync_exclude/d excludes all lines up to the rsync_exclude section entry
  • The /\[/,$d excludes everything from the start of the next section to the end of the file
  • The /^$/d excludes empty lines (this is optional)

All of the above extracts the relevant section from the config.

Parsing variables from config file in Bash

awk -F\= '{gsub(/"/,"",$2);print "Content of " $1 " is " $2}' <filename>

Just FYI, another pure bash solution

while read -r name value
echo "Content of $name is ${value//\"/}"
done < filename

bash reading and writing a config file with an unusual layout

For the first question, pre-process your .cfg file and then read it, like this:

sed 's/ = /=/g' < test.cfg > /tmp/processed.cfg
. /tmp/processed.cfg

Now, all your name_1, name_2 pairs will be available to your shell scripts.

For the second question, do it like this:

TARGET_KEY='name_1 '
sed -i -e "s/\($TARGET_KEY *= *\).*/\1$REPLACEMENT_VALUE/" $CONFIG_FILE

Reading a config file from a shell script

You don't want source it, so you should: the config, 2.verify lines 3.eval them

echo "=$ADMIN= =$TODO= =$FILE=" #these variables are not defined here
eval $(sed '/:/!d;/^ *#/d;s/:/ /;' < "$CONFIGFILE" | while read -r key val
#verify here
echo "$str"
echo =$ADMIN= =$TODO= =$FILE= #here are defined

sample of config file

ADMIN: root
TODO: delete


FILE: /path/to/file

if you run the above sample should get (not tested):

== == ==
=root= =delete= =/path/to/file=

sure this is not the best solution - maybe someone post a nicer one.

Edit a configuration file with sections using bash

Your current attempt has some problems.

# Your code
sed -i "s/^\s*($1\s*\).*\$/\1$2/" $3

After $1 you want at least one whitespace (you don't want to match key2), use '+'.

You would like the keep first whitespace(s) after the replacement, put it in the match.

Maybe you get additional spaces after a short key, so put the spaces after the key in the match too.

You don't want to match $. With the backslash it is a character. You don't need to match end-of-line, the .* will match everything until end-of-line.

How about a config file with a space in its name? Quote $3.

And the \s doesn't work in plain sed. Try -r.

I deleted the -i, so you can test without changing the file:

sed -r "s/^(\s*$1\s+).*$/\1$2/" "$3"

When you want to limit this code to a section, use /start/,/end/. How do you know something is a header? In your example the header lines are called header, but that will not be the case in your real config file. When the headers look like [section], change the solution beneath. The solution beneat assumes that all lines that don't start with whitespace is a header.

# Set a configuration value                                                                                                                                                                                        
# Args:
# 1) The config key
# 2) The new value
# 3) The config section header
# 4) The config file
function set_config_value() {
# first test this without the -i flag
sed -ir "/^${header}$/,/^[^\s]/ s/^(\s*${key}\s+).*$/\1${val}/" "${file}"

This solution should work for your sample config, but will fail when ${key} or ${value} has a special character (try key=/).

You should use a solution that doesn't try to understand the strings given. My first thought would be awk, but make your own choice. Look at .

how to parse a config file (*.conf) in shell script?

I'd do this:

pw=$(awk '/^password/{print $3}' app.conf)

user=$(awk '/^user/{print $3}' app.conf)

echo $pw

echo $user

The $() sets the variable pw to the output of the command inside. The command inside looks through your app.conf file for a line starting password and then prints the 3rd field in that line.


If you are going to parse a bunch of values out of your config file, I would make a variable for the config file name:

pw=$(awk '/^password/{print $3}' "${CONFIG}")
user=$(awk '/^user/{print $3}' "${CONFIG}")

Here's how to do the two different ports... by setting a flag to 1 when you come to the right section and exiting when you find the port.

mport=$(awk '/^\[MySQL\]/{f=1} f==1&&/^port/{print $3;exit}' "${CONFIG}")
sport=$(awk '/^\[Server\]/{f=1} f==1&&/^port/{print $3;exit}' "${CONFIG}")

bash: how to source array from section config file after sed?

source requires a file for an argument. Thus, replace:

source  $(sed -n '1,/animals/d;/\[/,$d;/^$/d;p;' config) 


source  <(sed -n '1,/animals/d;/\[/,$d;/^$/d;p;' config) 

The bash construct <(...) is called process substitution. It creates a file-like object that source can read from. It is in contrast to $(...) which is called command substitution which creates a string.

Related Topics

Leave a reply