Issue
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.
Solution
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:-
- 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, sayobject1
- 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}
- The condition
flag && NF
takes care of processing only non-empty lines and only property values after the requested object. - Now on the selected lines, using the
split()
function inAwk
, 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
Answered By - Inian