I have a shell script (let's call it produce.sh
) which outputs data in the following form, but does not save it to a file:
FOO=value
BAR=value2
ZAP=value3
I'd like to use these values as environment variables in a shell script. I'm currently doing this using the following shell code:
export $(./produce.sh)
This works great, except when the values to the right of the =
contain spaces. For instance:
FOO=split value
I've tried two different approaches in produce.sh
:
FOO="split value"
)FOO=split\ value
)Both of these do not work: if I inspect the environment variables, FOO
contains "split
in the first example and split\
in the second.
How can I get export
to handle this correctly?
The f
parameter expansion flag in zsh
will split an input on newlines, so this should handle input values with whitespace:
export ${(f)"$(./produce.sh)"}
The output from produce.sh:
=
.The parts of the substitution:
produce.sh
: generates the key-value output, for example: N=V1\nP=V 2\n
.$(...)
: command substitution. It is replaced with the output, minus trailing newlines: N=V1\nP=V 2
."..."
: the quotes ensure that the prior result is treated as a single term for the next step.${(f)...}
: expands that single term into multiple scalar values, splitting on newlines due to the (f)
flag. The result is effectively 'N=V1' 'P=V 2'
.export
: assigns and exports each parameter, acting like export 'N=V1' 'P=V 2'
.The substitution below adds some other cryptic zsh-isms to create an associative array. This avoids adding arbitrary variables to the consuming shell's environment:
% ./s2.sh
A=A
B=
C=C C
% typeset -A vals=("${(@s:=:)${(f)"$(./s2.sh)"}}")
% print ${vals[A]}
A
% print ${vals[C]}
C C
A minor tradeoff - this will not work if the value contains an equals, e.g.
D=D=D
.