Question

I need to retrieve the value of a key from an ini file with typical structure:

[abcd]
key1=a
key2=b
[efgh]
key1=c
key2=d
[hijk]
key1=e
key2=f

with key names repeated in different sections, and no consistant naming/order of sections. How could I find key1 from efgh? If I grep then I'll find all key1's (and I don't know the order of the sections).

I suspect sed or awk can do this but I can't find it...

Was it helpful?

Solution

This could be a start:

awk -F'=' -v section="[efgh]" -v k="key1"  '
$0==section{ f=1; next }  # Enable a flag when the line is like your section
/\[/{ f=0; next }         # For any lines with [ disable the flag
f && $1==k{ print $0 }    # If flag is set and first field is the key print key=value
' ini.file

You pass two variables, section and k. section needs to contain the section you want to look under. k should contain the key you are trying to obtain value for.

Find value of key1 under section [efgh]:

$ awk -F'=' -v section="[efgh]" -v k="key1"  '
$0==section{ f=1; next }  
/\[/{ f=0; next }         
f && $1==k{ print $0 }      
' ini.file
key1=c

Find value of key2 under section [hijk]:

$ awk -F'=' -v section="[hijk]" -v k="key2"  '
$0==section{ f=1; next }  
/\[/{ f=0; next }         
f && $1==k{ print $0 }      
' ini.file
key2=f

OTHER TIPS

Using sed

sed -r ':a;$!{N;ba};s/.*\[efgh\][^[]*(key1=[^\n]*).*/\1/' file

key1=c

another way

sed -nr '/\[efgh\]/,/\[/{/key1/p}' file

One way:

sed -n '/\[efgh\]/,/\[.*\]/p' file | awk -F= '/key2/{print $2}'

Using sed, extract the range of lines from [efgh] to the next [....] pattern. Using awk, search for key2 in this range of lines and get the value.

These sed one-liners worked for me, shamelessly copied from github:thomedes/ini.sed

#  List all [sections] of a .INI file
sed -n 's/^[ \t]*\[\(.*\)\].*/\1/p'

#  Read KEY from [SECTION]
sed -n '/^[ \t]*\[SECTION\]/,/\[/s/^[ \t]*KEY[ \t]*=[ \t]*//p'

#  Read all values from SECTION in a clean KEY=VALUE form
sed -n '/^[ \t]*\[SECTION\]/,/\[/s/^[ \t]*\([^#; \t][^ \t=]*\).*=[ \t]*\(.*\)/\1=\2/p'

# examples:
sed -n 's/^[ \t]*\[\(.*\)\].*/\1/p' /etc/samba/smb.conf
sed -n '/^[ \t]*\[global\]/,/\[/s/^[ \t]*workgroup[ \t]*=[ \t]*//p' /etc/samba/smb.conf
sed -n '/^[ \t]*\[global\]/,/\[/s/^[ \t]*\([^#; \t][^ \t=]*\).*=[ \t]*\(.*\)/\1=\2/p' /etc/samba/smb.conf

This might work for you (GNU sed):

sed -rn '/^\[/{h;d};G;s/^key1=(.*)\n\[efgh\]$/\1/p' file

Copy the section header and compare it against the section body.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top