reading properties from ini file in a bash script

2019-06-11 09:43发布

I am new to shell scripting, and I have a need which I am explaining by using a sample example. I have a property file which will contain data as shown below :

object1 : propertyA

object2 : property1 property2

object3 : propertyxyz

Note : On the whole I have some objects which can have any number of properties. And I need to keep this in a property files so that it can be changed as per need.

All I need is if I get object 3 as a user input then my code should print all the respective properties.

I have tried using .ini files, but I dont want to use any external parsers. And which ever comes with bash seems to not helping me in this case. if I use grep then I would have to split the properties using some regex.

.ini file which I created :

[object1]

property=propertyA


[object2]

property=property1

property=property2

[object3]

property=propertyxya

I am looking for a solution in which if I select an object ( which in case of ini files it is a section) then I should get all the properties in an array.

So is there any thing which is predefined in bash or do I need to write using grep n regex only.

标签: bash shell unix
4条回答
太酷不给撩
2楼-- · 2019-06-11 10:05

It can be done pretty easily using Awk, just do the below to store the contents in a bash array.

read -p "Enter object to get properties for: " objectname
all_properties=($(awk -F '=' -v input="${objectname}" '$1 ~ input{flag=1; next} $1 ~ /\[object/{flag=0; next} flag && NF {split($0,arr,"="); print arr[2] }  config.ini))

Now loop the array to print the properties,

for property in "${all_properties[@]}"; do
    printf "%s\n" "$property"
done

(or) just

printf "%s\n" "${all_properties[@]}"

The Awk command works as follows:-

  1. Getting the user input in a variable and passing to Awk using the -v syntax and doing a regex match $1 ~ input to match the line containing user input, say object1
  2. I am enabling a flag to start marking lines from this line on-wards and resetting the flag once the next object starts, see $1 ~ /\[object/{flag=0; next}
  3. The condition flag && NF takes care of processing only non-empty lines and only property values after the requested object.
  4. Now on the selected lines, using the split() function in Awk, we can extract the value of property and print it, which will be later stored in the array.

Put the line with read and the line below as shown in a bash script with she-bang set to #!/bin/bash and run it.

E.g. in a complete script as

#!/usr/bin/bash
read -p "Enter object to get properties for: " objectname
all_properties=($(awk -F '=' -v input="${objectname}" '$1 ~ input{flag=1; next} $1 ~ /\[object/{flag=0; next} flag && NF {split($0,arr,"="); print arr[2] }' config.ini ))

printf "%s\n" "${all_properties[@]}"

A few sample runs on the script.

$ bash script.sh
Enter object to get properties for: object1
propertyA

$ bash script.sh
Enter object to get properties for: object2
property1
property2

$ bash script.sh
Enter object to get properties for: object3
propertyxya
查看更多
ゆ 、 Hurt°
3楼-- · 2019-06-11 10:12

There is a project which provides a function to parse ini files: bash_ini_parser

It requires bash only, no other tools needed.

查看更多
爱情/是我丢掉的垃圾
4楼-- · 2019-06-11 10:16

I would do something like this, where XXXXXXX is the object name :

awk '/\[XXXXXXX\]/{flag=1;next}/\[.*\]/{flag=0}flag && NF' test.ini

For example :

awk '/\[object1\]/{flag=1;next}/\[.*\]/{flag=0}flag && NF' test.ini
property=propertyA

awk '/\[object2\]/{flag=1;next}/\[.*\]/{flag=0}flag && NF' test.ini
property=property1
property=property2

awk '/\[object3\]/{flag=1;next}/\[.*\]/{flag=0}flag && NF' test.ini
property=propertyxya

See this post for more info : How to select lines between two patterns?.

For the formatting in an array, it will depend what the array should look like

查看更多
戒情不戒烟
5楼-- · 2019-06-11 10:17

With awk we can have a regex for the [object] line and we just capture it. Then we have a regex for the property= line and, here, we join the object to the property:

awk '
/^\[[a-z0-9]*\]$/ { obj=$0 }
/^property=.*/ { print obj $0 }
' filename.ini

Which produces the intermediate output:

[object1]property=propertyA
[object2]property=property1
[object2]property=property2
[object3]property=propertyxya

Then, to get the properties, of, say, [object2], we simply use grep and sed:

obj=object2
result=$(echo $(awk '
/^\[[a-z0-9]*\]$/ { obj=$0 }
/^property=.*/ { print obj $0 }
' filename.ini | grep '^\['$obj'\]' | sed 's/.*property=//'))

This produces:

result=property1 property2
查看更多
登录 后发表回答