shell bash add tag
I've been working on a PostgreSQL deployment and decided to use the following pattern. 

1. separate service account for execution
2. single common "``" master script
3. dot-source environment-specific data at the head of ``

A _very_ minified example follows: 

$ cat
#!/usr/bin/env bash

. "./get-vars-$"

psql $PG_CONN \
    -c 'select now(), current_user, session_user;' \
    -f step-1.sql |& tee -a step-1.log

psql $PG_CONN \
    -c 'select now(), current_user, session_user;' \
    -f step-2.sql |& tee -a step-2.log

...where I have variables files for deploying to a docker instance as well as my localhost service...

$ cat
#!/usr/bin/env bash

PG_CONN=" -h $PG_URL \
-p $PG_PORT \

...and the only difference between them is as follows.

$ diff
< PG_PORT=5432
> PG_PORT=54320

During testing I noticed that tables were getting created with ownership assigned to the service account, so in the environments where it matters, I added `-c 'set role postgres; ' ` to the `$PG_CONN` variable. Sadly, this then threw an error...

$ psql $PG_CONN \
    -c 'select now(), current_user, session_user;' \
    -f step-1.sql | tee -a step-1.log
psql: warning: extra command-line argument "role" ignored
psql: warning: extra command-line argument "postgres;" ignored
psql: warning: extra command-line argument "'" ignored
Password for user deploy:
ERROR:  unterminated quoted string at or near "'set"
LINE 1: 'set
              now              | current_user | session_user
 2020-05-04 13:03:13.857168+01 | deploy       | deploy
(1 row)

psql:step-1.sql:1: NOTICE:  table "foo" does not exist, skipping


...and as you can seen the role assignment fails. I can work around this by either...

1. assigning the `set role` command in ``
2. wrapping the entire command in an `eval "psql $PG_CONN $(...)"` setup

...but I've been unable to properly escape the "`set role`" command inside the `$PG_CONN` variable directly. 

> How do I escape space literals for this use case?


Please find the raw repro docs [at this link][1]

Top Answer
Jack Douglas
You don't need to use `eval`, you can use [an array, instead of a simple text variable](


PG_CONN="-d postgres -c 'select 1'"
psql "${PG_CONN}" postgres

psql: FATAL:  database " postgres -c 'select 1'" does not exist


PG_CONN=(-d postgres -c 'select 1')
psql "${PG_CONN[@]}" postgres

Output format is wrapped.
Line style is unicode.
Border style is 2.
│ ?column? │
│        1 │

> Putting commands (or parts of commands) into variables and then getting them back out intact is complicated. When the shell expands a variable on the command line, if the variable was in double-quotes it's not parsed; if it was not in quotes, spaces in it are parsed as argument breaks, but quotes and escape are not parsed. In either case, putting quotes in the variable's value does nothing useful.

Enter question or answer id or url (and optionally further answer ids/urls from the same question) from

Separate each id/url with a space. No need to list your own answers; they will be imported automatically.