Reputation: 91149
I seem to be having issues with some shell scripting (ZSH in particular), where the shell fails to understand exports with spaces in them. The problem only happens when `runcommand` or $(runcommand) is used.
Test case:
# Works fine:
export test1="a b c"
# Does not work:
$(echo 'export test2="a b c"')
The error is something along the lines of export:4: not valid in this context: c"
. Adding 1-2 \
-escapes before the spaces and/or the quotes might change the error message to export:4: not valid in this context: b\
.
Might anyone have insight into what the problem is? Thank you.
(The reason I am doing this is a hack to allow python to set shell variables by dynamically generating code which gets run in .myshellrc; if anyone knows of a more elegant way to do this, that would be quite welcome as a comment. Thank you.) edit: To clarify, I am looking for a way to make the above work, or an alternative way to allow an external script to dictate what to export.
(*sigh*, I hope this isn't a version-specific issue in 4.3.12... I think this may have worked in the past.)
Upvotes: 1
Views: 999
Reputation: 86974
The issue here is that work splitting is done to the output before it is run as a command. What you end up with is export
being called with 3 arguments - test1="a
, b
, and c"
.
Using eval
as other answers have mentioned is one way to get around it.
An altenative solution would be to use process substitution. This is especially useful if your script is generating multiple lines of code.
Example:
zsh% source =(echo export test1=\"a b c\")
zsh% echo $test1
a b c
p.s. You might want to use the <(...)
syntax instead of =(...)
which will allow it to also work in bash.
Upvotes: 3
Reputation:
The usual way to do this is to use eval
as kev has said and pass it the full output of the program in question. The program should then produce valid shell code itself:
eval "$(your_script.py)"
And your_script.py
would print something like export var1="a b c"
(yes, using parenthesis in the output is OK).
An example of a program using this technique is rbenv. The user has to put eval "$(rbenv init -)"
in his shell init file, and rbenv init
actually outputs quite a lot of code:
export PATH="/opt/rbenv/shims:${PATH}"
source "/opt/rbenv/libexec/../completions/rbenv.zsh"
rbenv rehash 2>/dev/null
rbenv() {
local command="$1"
if [ "$#" -gt 0 ]; then
shift
fi
case "$command" in
shell)
eval `rbenv "sh-$command" "$@"`;;
*)
command rbenv "$command" "$@";;
esac
}
Upvotes: 2