Bash 4 introduced the ability to declare
and deal with associative arrays in a very pythonistic way, like so:
declare -A some_array # create the array
some_array[key] = 1 # put value
echo ${some_array[key]} # get value
Hooray! However, depending on the context, bash 4 or even older bash might not be available (this is typically the case with alpine based docker images). Here is an example based on database provisioning with pure sh
. Say you would like to create one database per user with their respective password (which is definitely calling for associative array). You would like to be able to do it this way in your docker-compose.yml
postgres:
image: postgres:12.1-alpine
restart: always
volumes:
- ./postgres_init:/docker-entrypoint-initdb.d
environment:
- POSTGRES_USER=P0stgr3sSup3rUs3r
- POSTGRES_PASSWORD=SomeAdminPassword
- POSTGRES_DBS=some_user->some_password|some_other_user->some_other_password
Here is what you need in your entrypoint.sh
#!/bin/sh
if [ -n "$POSTGRES_DBS" ]; then
IFS=\|
for s in $POSTGRES_DBS ; do
pass=$(echo "$s" | sed 's/.*->//');
user=$(echo "$s" | sed 's/->.*//');
db=$user"_db";
psql --username "$POSTGRES_USER" <<-EOSQL
CREATE USER $user WITH PASSWORD '$pass';
CREATE DATABASE $db;
REVOKE CONNECT ON DATABASE $db FROM PUBLIC;
GRANT ALL PRIVILEGES ON DATABASE $db TO $user;
ALTER DATABASE $db OWNER TO $user;
EOSQL
done
fi
We first set the Internal Field Separator IFS
to |
to ensure the first split to loop on. The second split level is made with sed
, first tacking the substring before ->
, then the one after.