1. Overview
Properties files contain properties names in the form of dot delimited strings.
This structure captures well the properties’ hierarchy. However, using such names directly is difficult in bash scripts.
In this tutorial, we’re going to access such properties with as few as possible changes to their name’s structure.
2. Problem Statement
Let’s examine a simple property file test.properties:
# test.properties
db.test.user=test user
db.test.passwd=password
As the first attempt, let’s turn properties names into bash variables. For this purpose, let’s just source the properties file:
#!/bin/bash
source test.properties
echo "User Id (db.test.user) = " $db.test.user
echo "user password (db.test.passwd) =" $db.test.passwd
Unfortunately, we’re going to end up with errors:
test.properties: line 2: db.test.user=test user: command not found
test.properties: line 3: db.test.passwd=password: command not found
User Id (db.test.user) = .test.user
user password (db.test.passwd) = .test.passwd
This approach fails because the dot is an illegal character in the bash variable’s name.
3. Mapping out Dots From the Property Name
Let’s just change the dots into some legal character.
The bash variable’s name may contain only digits, letters, and underscores. Therefore we need to choose the underscore ‘_’:
#!/bin/sh
file="./test.properties"
while IFS='=' read -r key value
do
key=$(echo $key | tr '.' '_')
eval ${key}=\${value}
done < "$file"
echo "User Id (db.test.user) = " ${db_test_user}
echo "user password (db.test.passwd) = " ${db_test_passwd}
We read key and value separately, with the equal sign as a separator. Next, tr translates dots to underscores in the property name. Finally, eval defines a bash variable with a new name.
Now let’s examine the result produced by this script:
User Id (db.test.user) = test user
user password (db.test.passwd) = password
Within this approach, we create a bunch of bash variables, one for each property. Subsequently, we refer to properties using mapped names.
4. Use Array as a Lookup Table
Since Bash 4.0, we can benefit from associative arrays. So, let’s use the property’s name as a key to its values:
#!/bin/bash
# array declaration
declare -A props
file="./test.properties"
while IFS='=' read -r key value; do
props["$key"]="$value"
done < "$file"
echo "User Id (db.test.user) = " ${props["db.test.user"]}
echo "user password (db.test.passwd) = " ${props["db.test.passwd"]}
The key has no limitations on its form. Therefore we can access properties with their own names.
5. Picking out Variables From File With a Wrapper Function
Let’s create a function that searches for a property’s name in the properties file. As a result, it returns the property’s value.
Under the hood, we’re going to use the grep command and subsequently cut off the property value from the found line:
#!/bin/bash
file="./test.properties"
function prop {
grep "${1}" ${file} | cut -d'=' -f2
}
echo "User Id (db.test.user) = " $(prop 'db.test.user')
echo "user password (db.test.passwd) = " $(prop 'db.test.passwd')
We refer to the property using its original name. However, each picking of variable demands grepping the whole file again. Therefore, this method may be slow for large property files.
6. Conclusion
In this article, we learned how to parse a properties file.
First, we kept the properties as bash variables at the cost of modifying their names.
Next, we stored them in the associative array, which returned the value bound to a given name.
Finally, we just searched for properties in the file using grep.