0

Let's consider these 2 psql commands of 2 different difficulties:

First one - the easy: select * from myproducts where price = 600;

Second one - the harder: select * from myproducts where metadata @> '{"product-id": "aaa-bbb-ccc-ddd"}';

When I try to put them into a zsh script, I manage to do it for the first one, as follows:

#!/usr/bin/env zsh

#Lets take for granted I'm already connected to that db
"psql -d mycooldb -c 'select * from myproducts where price = 600;' "

Executing that script above works pretty good.

But when I try to do it with the second psql command - the harder - I never manage to handle the big quantity of quotes and my zsh script always fails (mostly syntax failures from the quotes confusion), I have something that looks like:

#!/usr/bin/env zsh

"psql -d mycooldb -c 'select * from myproducts where metadata @> '{"product-id": "aaa-bbb-ccc-ddd"}';' "

I've tried to use variables for "product-id" and its value, but (without a big surprise) it doesn't work, as well as trying to escape some quotes. I might be escaping them wrongly though.

Does anyone has a clue on how I could handle the harder psql command into a zsh script ? Thanks

Stan Amsellem
  • 503
  • 1
  • 5
  • 16
  • 1
    Wrap in single quotes. Escape single quotes as `'\''` (which technically isn't escaping them, it's string concatenation, but that's not important) – jeremysprofile Jan 28 '20 at 19:19
  • The example "working" command can't possibly work as written here with the outer double-quotes; just as `"ls /tmp"` tries to run a command called `tmp` in a directory named `ls` and thus causes a command-not-found, your command is looking for a command that has `psql -d` *including the space and the argument* as part of its name; no such file exists. – Charles Duffy Jan 28 '20 at 19:22
  • Also, `zsh` and `bash` are two different shells, and they're mutually incompatible with each other. If you're using zsh, tag for zsh; *don't* tag for bash. – Charles Duffy Jan 28 '20 at 19:23
  • just changed `bash` occurences in my description to `zsh`. I've checked the duplicate question/answer, and the `$'product-id'` solution doesn't seem to work here. I've tried various combinations on this part `'{"product-id": "aaa-bbb-ccc-ddd"}'` but that doesn't work. Would be much appreciated if you could please @CharlesDuffy give a clue or de-duplicate the question ? thanks – Stan Amsellem Jan 28 '20 at 19:34
  • I'm actually pretty sure zsh does in fact support that syntax and thus that the answer should apply. I'll test when I get back to my laptop and provide you with an example. – Charles Duffy Jan 28 '20 at 20:29
  • thanks @CharlesDuffy, I appreciate that – Stan Amsellem Jan 28 '20 at 20:33
  • `psql -d mycooldb -c $'select * from myproducts where metadata @> \'{"product-id": "aaa-bbb-ccc-ddd"}\';'` -- note the removal of the outer double-quotes; as I said before, there's no possible way your script could work with them there. – Charles Duffy Jan 28 '20 at 20:49
  • 1
    btw, to test how a command will be parsed into individual arguments, a tool you might consider is `printf '%s\n' ...that command...`, which will print each argument, after quote removal and parameter expansions are done, on a separate line. Doesn't help if your arguments can contain literal newlines, but as long as they don't, it's useful. Thus, `printf '%s\n' echo "hello world" "goodbye world"` prints `echo` on one line, `hello world` on another, `goodbye world` on a third. – Charles Duffy Jan 28 '20 at 20:51
  • 1
    ...with the above command, running `printf '%s\n' psql -d mycooldb -c $'select * from myproducts where metadata @> \'{"product-id": "aaa-bbb-ccc-ddd"}\';'` in zsh 5.7.1 prints the last line as `select * from myproducts where metadata @> '{"product-id": "aaa-bbb-ccc-ddd"}';`, which as I understand it is the argument you expect to be passed to `psql`. – Charles Duffy Jan 28 '20 at 20:52
  • 1
    BTW, that's the same output as what you get from `printf '%s\n' psql -d mycooldb -c 'select * from myproducts where metadata @> '\''{"product-id": "aaa-bbb-ccc-ddd"}'\'';'`, following the practice @jeremysprofile suggested in the first comment on the question. Just take out the `printf '%s\n'` prefix and you have a command ready-to-use in a script. – Charles Duffy Jan 28 '20 at 21:11

0 Answers0