6

I have one Configuration file with section wise data, as mentioned below. Using shell script accessing each variable. I am using sed command for that, Now I facing one problem like if I forget to configure one variable example:name [APP1] it will take [APP2] name.
Config File:

[APP1]
name=Application1
StatusScript=/home/status_APP1.sh
startScript=/home/start_APP1.sh
stopScript=/home/stop_APP1.sh
restartScript=/home/restart.APP1.sh

[APP2]
name=Application2
StatusScript=/home/status_APP2.sh
startScript=/home/start_APP2.sh
stopScript=/home/stop_APP2.sh
restartScript=/home/restart.APP2.sh
logdir=/log/APP2/
.
.
.
.
.
[APPN]
name=ApplicationN
StatusScript=/home/status_APPN.sh
startScript=/home/start_APPN.sh
stopScript=/home/stop_APPN.sh
restartScript=/home/restart.APPN.sh
logdir=/log/APPN

shell command using :

sed -nr "/^\[APP1\]/ { :l /^name[ ]*=/ { s/.*=[ ]*//; p; q;}; n; b l;}"

Is there any way to solve this problem, if some variable not configured under one section it through null or 0 as the variable value.

3 Answers 3

4

Parse your configuration into an unambiguous format, then read it into an associative array in a recent release of bash:

awk '/^\[/ { app=substr($0,2,length-2) } /=/ { print app "." $0 }' file.conf

This finds all section headers and sets the awk variable app to the contents of these. It then prefixes each following line with that value followed by a dot.

This would create output like

APP1.name=Application1
APP1.StatusScript=/home/status_APP1.sh
APP1.startScript=/home/start_APP1.sh
APP1.stopScript=/home/stop_APP1.sh
APP1.restartScript=/home/restart.APP1.sh
APP2.name=Application2
APP2.StatusScript=/home/status_APP2.sh
APP2.startScript=/home/start_APP2.sh
APP2.stopScript=/home/stop_APP2.sh
APP2.restartScript=/home/restart.APP2.sh
APP2.logdir=/log/APP2/

If your APP2 lacked a name subsection, the APP2.name line would not show up.

Then read this into an associative array in bash:

declare -A conf
while IFS='=' read -r key value; do
    conf[$key]="$value"
done < <(awk '/^\[/ { app=substr($0,2,length-2) } /=/ { print app "." $0 }' file.conf)

You may now query the conf variable for your configuration:

printf 'The stopScript for APPN is "%s"\n' "${conf[APPN.stopScript]}"

This will return

The stopScript for APPN is "/home/stop_APPN.sh"

Querying a non-existing value will yield an empty string.


The awk command could also be replace by the following sed command:

sed -n \
    -e '/^\[/{s/[][]//g;h;}' \
    -e '/=/{H;g;s/\n/./;p;s/\..*//;h;}' file.conf

Expanded and annotated:

/^\[/{          # handle section headers
    s/[][]//g;  # remove [ and ]
    h;          # put into the hold-space
}

/=/{            # handle settings
    H;          # append the line to the hold-space with newline as delimiter
    g;          # get the hold-space
    s/\n/./;    # replace the newline with a dot
    p;          # output
    s/\..*//;   # remove everything after the dot
    h;          # put back into the hold-space
}
3

You can create a shell function like this:

printSection()
{
  section="$1"
  found=false
  while read line
  do
    [[ $found == false && "$line" != "[$section]" ]] &&  continue
    [[ $found == true && "${line:0:1}" = '[' ]] && break
    found=true
    echo "$line"
  done
}

You can then use printSection like a command, and pass in the section as a parameter like:

printSection APP2

To get your parameter, you can use a much simpler sed now, like:

printSection APP2 | sed -n 's/^name=//p'

This will be operating on stdin and writing to stdout. So if your example config file were called named /etc/application.conf, and you wanted to store the name of APP2 in a variable app2name, you could write this:

app2name=$(printSection APP2 | sed -n 's/^name//p/' < /etc/applications.conf)

Or, you could build the parameter part into the function and skip sed altogether, like this:

printValue()
{
  section="$1"
  param="$2"
  found=false
  while read line
  do
    [[ $found == false && "$line" != "[$section]" ]] &&  continue
    [[ $found == true && "${line:0:1}" = '[' ]] && break
    found=true
    [[ "${line%=*}" == "$param" ]] && { echo "${line#*=}"; break; }
  done
}

Then you would assign your var like this:

app2name=$(printValue APP2 name < /etc/applications.conf)
1
  • 1
    I'm terribly sorry, I was adding stuff to your answer that should have been in my answer! Duh. I've restored it now. Need more coffee...
    – Kusalananda
    Commented May 19, 2018 at 8:13
1

If you have access to Git, you can "abuse" its config functionality to query the config file:

git config --file /etc/applications.cfg --get APPN.stopScript

You can also list all key/value pairs in section.key=value format using the --list argument

git config --file /etc/applications.cfg --list

However, I was not able to figure out the way to list a single section.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .