I need to write a Ruby function which generates a correct Bash export statement given a variable name and the value it should be assigned to. My current attempt is
def export(variable, string)
"export #{variable}=#{Shellwords.escape(string)}"
end
However, it doesn't behave quite as I expect. E.g.
[2] pry(main)> export("X", "a\nb")
"export X=a'\n'b"
and then
export X=a'\n'b
echo "$X"
in the shell gives
a\nb
instead of the desired
a
b
If it matters (I don't expect it to, but just in case) the statement will be written into a file which will be sourced later.
You're copy-pasting the auto-echoed string from irb
, not the value of said string. The auto-echoing is showing you a Ruby string literal with Ruby escapes left in, so you get:
irb(main)> Shellwords.shellescape("a\nb")
=> "a'\n'b"
If you printed that string (e.g. with puts
) to get its raw value (with the escapes printed as their real characters), e.g.
irb(main)> puts Shellwords.shellescape("a\nb")
a'
'b
=> nil
and copy-pasted that to make:
export X=a'
'b
echo "$X"
it would work just fine.
Similarly, writing "export X=#{Shellwords.escape(string)}"
to a file (via puts
or other actual I/O APIs that write the string's value, not its representation) for later use would work just fine, because that would be inserting the string's value, and the file would end up with a raw newline between the single-quotes, not \n
.