udaya
udaya

Reputation: 77

Need a help on fetching value based on a key from a config file

I have a file containing similar data

[xxx]

name = xxx
address = bangalore

[yyy]

name = yyy
address = sjc

Please help me getting a regex that I can fetch the address/name value based on xxx or yyy (xxx or yyy and address or name is the input)

Upvotes: 1

Views: 99

Answers (3)

dawg
dawg

Reputation: 103864

You can do something like this with awk if your file is just like that (i.e., the name is the same as the section and it is before the address):

$ awk -v nm='yyy' -F ' *= *' '$1=="name" && $2==nm{infi=1; next}
                              $1=="address" && infi {print $2; infi=0}' file
sjc

Or, better still you can get the section and then fetch the key, value as they occur and print them and then exit:

$ awk -v sec='yyy' -v key='address' '
                    BEGIN{
                          FS=" *= *"
                          pat=sprintf("^\\[%s\\]", sec)} 
                    $0 ~ pat {secin=$1; next}
                    NF==2 && $1==key && secin ~ pat {print $2; exit}' file
sjc 

If you want to gather all sections with their key/value pairs, you can do (with gawk):

$ gawk 'BEGIN{FS=" *= *"}
       /^\[[^\]]+\]/ && NF==1 {sec=$1; next} 
       NF==2 {d[sec][$1]=$2}
       END{ for (k in d){
                printf "%s: ",k
                for (v in d[k])
                    printf "\t%s = %s\n", v, d[k][v]
                        }
           }' file
[xxx]:  address = bangalore
        name = xxx
[yyy]:  address = sjc
        name = yyy

Config or .ini files can have quoting like csv, so it is best to use a full config file parser. You can use Perl or Python that have robust libraries for parsing .ini or config type files.

Python example:

#!/usr/bin/python

import ConfigParser
config = ConfigParser.ConfigParser()
config.read("/tmp/file")

Then you can grab the sections, the items in each section, or a specific items in a specific section:

>>> config.sections()
['xxx', 'yyy']
>>> config.items("yyy")
[('name', 'yyy'), ('address', 'sjc')]
>>> config.get("xxx", "address")
'bangalore'

Upvotes: 2

Ed Morton
Ed Morton

Reputation: 203645

It's not clear if you're trying to search for the value inside the square brackets or the value of the "name" tag but here's a solution to one possible interpretation of your question:

$ cat tst.awk
BEGIN { FS=" *= *" }
!NF   { next }
NF<2  { prt(); k=$0 }
      { map[$1] = $2 }
END   { prt() }
function prt() { if (k=="["key"]") print map[tag]; delete map }

$ awk -v key='yyy' -v tag='address' -f tst.awk file
sjc

$ awk -v key='xxx' -v tag='address' -f tst.awk file
bangalore

$ awk -v key='xxx' -v tag='name' -f tst.awk file
xxx

Upvotes: 0

Jan
Jan

Reputation: 43169

Regex to the rescue!
This approach splits the entries into single elements and parses the key-value-pairs afterwards. In the end, you can simply ask your resulting dictionary for ie. values['xxx'].
See a demo on ideone.com.

import re

string = """
[xxx]

name = xxx
address = bangalore

[yyy]

name = yyy
address = sjc
"""

rx_item = re.compile(r'''
    ^\[(?P<name>[^][]*)\]
    .*?
    (?=^\[[^][]*\]$|\Z)
    ''', re.X | re.M | re.DOTALL)

rx_value = re.compile(r'^(?P<key>\w+)\s*=\s*(?P<value>.+)$', re.MULTILINE)

values = {item.group('name'): {
            m.group('key'): m.group('value') 
            for m in rx_value.finditer(item.group(0))}
            for item in rx_item.finditer(string)
        }

print(values)
# {'xxx': {'name': 'xxx', 'address': 'bangalore'}, 'yyy': {'name': 'yyy', 'address': 'sjc'}}

Upvotes: 2

Related Questions