-1

I have this situation:

source local.env
run_my_app

In local.env, I have a bunch of environment variabless that pertain specifically to run_my_app, like this:

es_protocol="http"
es_host=0.0.0.0
es_port=9200

mongo_protocol=mongodb+srv
mongo_host=foo.cluster.mongodb.net
mongo_port=80
mongo_user=foo

rabbit_protocol=ampq
rabbit_host=foo.rabbitmq.svc.cluster.local
rabbit_port=5672
rabbit_user=rabbitmq

Instead of adding a prefix my_app to every variable in the file which is redundant and noisy, I want to add a prefix using a shell program, something like this:

source <(add_var_prefix 'my_app' local.env)  ## *note below

Does anyone know how to implement a Bash function like add_var_prefix that can do 2 things:

  1. add the prefix to all variables in the local.env file
  2. export the variables instead of just sourcing
  • note that source <(xyz) won't work because source doesn't work with process substitution for some ungodly reason
2
  • 1
    Remember, shell command streams are just text files. Have you tried sed?
    – Jim L.
    Nov 29, 2023 at 16:52
  • @JimL. not sure I follow what you mean, all I know is that source cannot work with process substitution, so I will add a comment to OP Nov 29, 2023 at 17:02

2 Answers 2

2

Here is a naive solution using sed:

source <(sed 's/[^=]\+=/export my_app_&/' local.env)

I call this "naive" because I assume that each line containing an equal sign is a variable assignment, and I do not take into account any fancy formatting, like multi-line variables or several assignments on the same line.

2
  • sadly source doesn't work with process substitution, like the 4th time I have tried this, every 18 months I forget that bash cannot do that, it's the WORST Nov 29, 2023 at 17:00
  • 3
    I've just tried it with Bash 5.1.16 and this works as expected. I also did this several years ago, probably with Bash 4. Try it: source <(printf 'echo It works')
    – xhienne
    Nov 29, 2023 at 17:03
1

A slight addition to @xhienne's answer, with a regexp that will recognize # at beginning-of-line as a comment, and some QED exercises showing that both sourcing and exporting work using this techique.

From a fresh shell:

$ set | grep prefix
$ bash -l
$ prefix=my_prefix
$ source <(sed -Ee "s/^([^#])/${prefix}_\1/" local.env)

I can now confirm that my environment has several lines of content matching "prefix":

$ set | grep prefix
my_prefix_es_host=0.0.0.0
my_prefix_es_port=9200
my_prefix_es_protocol=http
my_prefix_mongo_host=foo.cluster.mongodb.net
my_prefix_mongo_port=80
my_prefix_mongo_protocol=mongodb+srv
my_prefix_mongo_user=foo
my_prefix_rabbit_host=foo.rabbitmq.svc.cluster.local
my_prefix_rabbit_port=5672
my_prefix_rabbit_protocol=ampq
my_prefix_rabbit_user=rabbitmq
prefix=my_prefix

Opening a subshell and checking again confirms that none of those variables are exported:

$ bash -l
$ set | grep prefix
$ ^D
logout
$ ^D
logout

Back to a clean shell:

$ set | grep prefix
$ bash -l
$ prefix=my_prefix

This time we'll export all those variables:

$ source <(sed -Ee "s/^([^#])/export ${prefix}_\1/" local.env)

Here they are in the parent shell:

$ set | grep prefix
my_prefix_es_host=0.0.0.0
my_prefix_es_port=9200
my_prefix_es_protocol=http
my_prefix_mongo_host=foo.cluster.mongodb.net
my_prefix_mongo_port=80
my_prefix_mongo_protocol=mongodb+srv
my_prefix_mongo_user=foo
my_prefix_rabbit_host=foo.rabbitmq.svc.cluster.local
my_prefix_rabbit_port=5672
my_prefix_rabbit_protocol=ampq
my_prefix_rabbit_user=rabbitmq
prefix=my_prefix

And if we open a child shell, the variables appear there also:

$ bash -l
$ set | grep prefix
my_prefix_es_host=0.0.0.0
my_prefix_es_port=9200
my_prefix_es_protocol=http
my_prefix_mongo_host=foo.cluster.mongodb.net
my_prefix_mongo_port=80
my_prefix_mongo_protocol=mongodb+srv
my_prefix_mongo_user=foo
my_prefix_rabbit_host=foo.rabbitmq.svc.cluster.local
my_prefix_rabbit_port=5672
my_prefix_rabbit_protocol=ampq
my_prefix_rabbit_user=rabbitmq
$ ^D
logout
$ ^D
logout

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .