Angelo
Angelo

Reputation: 111

How to pass a json body from ruby to bash script

I am trying to study both bash and ruby and I am trying to pass a variable that contains a JSON object from ruby to be printed using a bash script.

I tried storing the JSON object in a variable then used that variable as an argument for my bash script but I am not getting the result that I wanted.

so in my ruby code I have this:

param = request.body
cmd = "ruby_to_bash #{param}"
exec cmd

and in my bash script, I am simply outputting the value of the argument:

echo $1

For example I have this JSON:

{"first":"one","second":"two","third":"three"}

my code only gives me this output:

{first:

I want to display the whole JSON object. How can I do this? Any kind of help will be much appreciated.

Upvotes: 1

Views: 832

Answers (2)

mu is too short
mu is too short

Reputation: 434735

I think your best bet is, as usual in such cases, not to involve a shell at all.

When you say this:

cmd = "ruby_to_bash #{param}"
exec cmd

Your exec call is invoking a shell which parses cmd and then runs ruby_to_bash so you're doing this:

  1. Build a command line.
  2. Replace the current process with /bin/sh.
  3. /bin/sh parses the command line that you should mashed together. This is where you need to worry about quoting and escaping to get past the shell.
  4. /bin/sh exec's ruby_to_bash.

You could bypass the whole problem by using the multi-argument form of Kernel#exec:

exec(cmdname, arg1, ...)
command name and one or more arguments (no shell)

which doesn't bother with a shell at all. If you say:

exec 'ruby_to_bash', param

You won't involve a shell and the quotes or spacing in param won't matter to anyone other than ruby_to_bash.

Upvotes: 1

Aleksei Matiushkin
Aleksei Matiushkin

Reputation: 121000

Both bash and ruby treat double quotes in a kinda special way: double-quoted strings are interpolated before passed to the receiver. I strongly encourage you to start with learning somewhat one in the first place instead of doing zero progress in both due to induced errors.

Answering the question stated, one must escape double quotes when passing back and forth since both ruby and bash treat them as content delimiters and discard when the content is already parsed in the resulting string.

This would work:

exec %|ruby_to_bash #{param.gsub('"', '\"')}|

I use %| and | as string delimiters to avoid clashes against inner quotes.


Sidenote: the above won’t work for the input containing spaces, but I purposely avoid to show how to deal with spaces since it leads to the dead end; once handled spaces with surrounding the interpolated param with single quotes, we are prone to be screwed up with inner single quotes in JSON object and so forth.

The code above is not someone should ever produce in production.

Upvotes: 1

Related Questions