The standard command to output all the environment variables mapped to shell variables as shell code that can be interpreted to set the same environment variables is export -p
. export
will take care of quoting the value as appropriate.
In the case bash
's export
though, you need the posix
option to be enabled (like when it's invoked as sh
) for that output to be in sh
-compatible syntax.
(set -o posix; export -p)
Though note that bash's export
does use the "..."
quotes for some values, which is not reliable when used with non ASCII text as the code may be interpreted differently when run in a different locale.
Also note that if a shell variable has been exported and not given any value, it will give: export variable
.
Doing:
sh -c 'export -p'
Would address the latter, and potentially also the former if your sh
is not bash
and uses the safer single quotes to quote the values.
If you consider that arbitrary environment variable values and names can contain newline characters (or single quotes or double quotes or non-text for that matters), it should become evident that the output of printenv
cannot be post-processed reliably with line-based text utilities.
For example, with printenv
here called with one (weirdly named) environment variable:
$ env -i $'$(reboot)\n=\n"$(reboot)"=\n$(reboot)' printenv
$(reboot)
=
"$(reboot)"=
$(reboot)
With the GNU implementations of printenv
and awk
, you could however do something reliable if limiting for instance to environment variables that are mappable to shell variables and whose name starts with DB_MYSQL_
:
printenv -0 | LC_ALL=C gawk -v 'RS=\0' -v q="'" '
function shquote(s) {
gsub(q, q "\\" q q, s)
return q s q
}
match($0, /^(DB_MYSQL_[_[:alnum:]]*=)(.*)$/, capture) {
print "export " capture[1] shquote(capture[2])
}'
Where the -0
aka --null
option of printenv
causes printenv
to print the environment variables NUL-delimited (and NUL contrary to newline cannot occur in an environment name nor value), and we use single quotes instead of double quotes (with '
in values inserted as \'
outside of quotes), amd LC_ALL=C
for every byte value to be considered valid text and the [:alnum:]
character class to be limited to a-zA-Z0-9.
With zsh
, you can do:
vars=(${(Mk)parameters[(R)scalar-export]:#DB_MYSQL_*})
(($#vars)) && export -p $vars
To print the definitions of scalar exported shell variables whose name starts with DB_MYSQL_
. zsh
's export
doesn't use "..."
quoting but may use $'...'
or leave some non-ASCII characters unquoted, which could also be a problem if the generate code is interpreted in a different locale from that where the code has been generated.
set -o extendedglob
for var (${(Mk)parameters[(R)scalar-export]:#DB_MYSQL_[a-zA-Z0-9_]#})
print -r export $var=${(Pqq)var}
Where we always use single quotes and skip variable names with non-ASCII alnums would make it safer.
$
, backslash, backtick (and obviously"
) are still a problem (and potentially characters whose encoding contains the encoding of those which in practice happens for backslash and backtick in some locales). Single quotes are a much better choice, though you'd still need to handle'
specially. See also Escape a variable for use as content of another script – Stéphane Chazelas Mar 28 '22 at 14:22declare -x -p
would be more robust than trying to wrangle the output ofprintenv
? – steeldriver Mar 28 '22 at 15:32bash
tag – steeldriver Mar 28 '22 at 16:30printenv
, likels
, is (arguably) a useful tool for producing output for display to users, but not for providing input to programs. There; I said it. :-) I see now that Stéphane Chazelas said this in his answer (although not in his comment). – G-Man Says 'Reinstate Monica' Apr 06 '22 at 19:17