2015-03-07 16:46:52 -0600, Alan Wild: > I'm really curious to see if anyone else offers better ideas, but the ways > I've done this are > > 1) exactly what you propose. > > 2) use a subshell (parantheses): > > $ ( for x in a b c; { echo $x; } ) > a > b > c > $ typeset -p x > bash: typeset: x: not found > > 3) use a function and declare x local to the function > > $ function f() { local x; for x; { echo "$x"; }; } > $ f a b c > a > b > c > $ typeset -p x > bash: typeset: x: not found [...]
Another solution: $ x=1 $ x= eval 'for x in 2 3 4; do :; done' $ echo "$x" 1 That won't work in POSIX mode though: $ set -o posix $ x= eval 'for x in 2 3 4; do :; done' $ echo "$x" 4 eval being a special builtin, variable passed that way are required to retain their value when the command returns. You can remove the "special" attribute with "command". $ x= command eval 'for x in 5 6 7; do :; done' $ echo "$x" 4 BTW, to get back on topic: $ bash --norc -o posix bash-4.3$ unset zzz bash-4.3$ zzz=x eval bash-4.3$ env | grep zzz zzz=x ksh93, zsh (in sh emulation), dash, mksh, the Bourne shell (the port of opensolaris' to Linux at least) do retain the value of zzz after eval has returned but don't export it to the environment. They don't export it within the evaled code either. $ ksh -c 'zzz=x eval "env | grep zzz"' $ yash behaves like bash. If I interpret the POSIX spec correctly, the variable should *not* be exported in those cases (though it's not very clear): http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_09_01 SUSv4> If no command name results, or if the command name is a SUSv4> special built-in or function, variable assignments shall SUSv4> affect the current execution environment. Otherwise, the SUSv4> variable assignments shall be exported for the execution SUSv4> environment of the command and shall not affect the current SUSv4> execution environment except as a side-effect of the SUSv4> expansions performed in step 4. For functions, mksh, yash and zsh behave like bash (again, against POSIX it would seem) in: $ bash -c 'f() { env | grep zzz; }; zzz=x f' zzz=x -- Stephane