print environment variables sorted by name including variables with newlines

Viewed 5145

I couldn't find an existing answer to this specific case: I would like to simply display all exported environment variables sorted by their name. Normally I can do this like simply like:

$ env | sort

However, if some environment variables contain newlines in their values (as is the case on the CI system I'm working with), this does not work because the multi-line values will get mixed up with other variables.

4 Answers

Answering my own question since I couldn't find this elsewhere:

$ env -0 | sort -z | tr '\0' '\n'

env -0 separates each variable by a null character (which is more-or-less how they are already stored internally). sort -z uses null characters instead of newlines as the delimiter for fields to be sorted, and finally tr '\0' '\n' replaces the nulls with newlines again.

Note: env -0 and sort -z are non-standard extensions provided by the GNU coreutils versions of these utilities. Open to other ideas for how to do this with POSIX sort--I'm sure it is possible but it might require a for loop or something; not as easy as a one-liner.

The bash builtin export prints a sorted list of envars:

export -p | sed 's/declare -x //'

Similarly, to print a sorted list of exported functions (without their definitions):

export -f | grep 'declare -fx' | sed 's/declare -fx //' 
env | sort -f

Worked for me.

The -f option makes sort ignore case, which is what you probably want 99% of the time

In a limited environment where env -0 is not available, eg. Alpine 3.13, 3.14 (commands are simplified busybox versions) you can use awk:

awk 'BEGIN { for (K in ENVIRON) { printf "%s=%s%c", K, ENVIRON[K], 0; }}' | sort -z | tr '\0' '\n'

This uses awk to print each environment variable terminated with a null, simulating env -0. Note that setting ORS to null (-vORS='\0') does not work in this limited version of awk, neither does directly printing \0 in the printf, hence the %c to print 0.
Busybox awk lacks any sort functions, hence the remainder of the answer is the same as the top one.

Related