0

I have a perl module that gives me a string with key=value pairs that are meant to be used as environment variables to another script.
But when I do in the command line:

$(perl -I/foo -MFoo=vars -E'say vars()') script

I get errors from bash. How should I be using the command?

If I run:
perl -I/foo -MFoo=vars -E'say vars()' and then copy paste and run it works i.e.

K1=V1 K2=V2 K3=V3 script

I want to avoid having export

Jim
  • 3,845
  • 3
  • 22
  • 47
  • You cannot provide multi-line strings as as local env variables to command – Inian Aug 16 '23 at 11:10
  • @Inian: It is one line i.e. no new line chars – Jim Aug 16 '23 at 11:11
  • Ah! It could be a single long string with space separated k/v pairs, which bash treats as one long string. But in reality it needs separate arguments etc – Inian Aug 16 '23 at 11:14
  • @Inian: I am not sure I get what you mean by separate arguments – Jim Aug 16 '23 at 11:18
  • Could you paste the exact error shown? – Inian Aug 16 '23 at 11:20
  • What does the sentence _a perl module that gives me a string_. A module is **giving** a **string**? I don't think that a module can "give" anything. – user1934428 Aug 16 '23 at 11:26
  • I can see from _K1=V1 K2=V2 K3=V3 script_, that you set the environment variables K1, K2 and K3 for running a program named `script`, but I don't see what's the problem is with this. _I want to avoid having export_ : There is no `export` command in your posting. I simply don't understand your problem here. Please provide a simple, reproducible example. – user1934428 Aug 16 '23 at 11:29
  • This is what `eval` is for. https://unix.stackexchange.com/questions/4984/ – jqurious Aug 16 '23 at 12:13

1 Answers1

4

Problem

Bash can only accept key/value arguments local to the command as long as they are separate pairs and not a full string containing all the key/value pairs concatenated together,

i.e. if you have a script (test.bash) containing

echo "$FOO"
echo "$BAR"

and doing

FOO=foo BAR=bar bash test.bash

produces

foo
bar

but the same doesn't work, if you pass those key/value pairs as a single string. i.e.

x='FOO=foo BAR=bar'
"$x" bash test.bash

cannot work, because the order of shell expansions doesn't allow that. By the time the variable expansion of x happens, the command is evaluated with the expanded value as below. The re-processing of the command line variables doesn't happen again.

'FOO=foo BAR=bar' bash test.bash

which is not correct, as the whole literal string 'FOO=foo BAR=bar' is treated as a one long command.

Solution

You could use the env command directly with the -S flag to pass each k/v pair into the environment, in which the script is run

env -S "$(perl -I/foo -MFoo=vars -E'say vars()')" script

By doing the above, each k/v pair in is added as additional environment variables to the shell in which the script is being run. Also note that -S is not portable (not POSIX compliant).

Inian
  • 80,270
  • 14
  • 142
  • 161