2

Consider I want to programmatically read the environment of an interactive shell. Now, starting a shell, running /usr/bin/env and capturing its output seems like a good solution. But only up until the moment we realize that variable values can have line breaks:

$ export LINE0='VALUE0
> LINE1=VALUE1'
$ env | grep ^LINE
LINE0=VALUE0
LINE1=VALUE1

So capturing the output of env -0 (NULL-separated entries) seems like a better approach, but this only applies to GNU env, so is mostly Linux-specific.

Is there any portable (POSIX or BSD) way to get the NULL-separated list of environment variables, using only the standard command line tools (may use awk, but no perl/python/ruby allowed)?

1
  • 3
    That's a shame, because portable but not standardized tools exist. printenv for just one example. Commented Feb 28, 2020 at 11:56

1 Answer 1

3

I wonder how you plan to restore that captured environment, since no shell but zsh supports nul bytes in its variables.

Anyways, you could use awk to escape \ as \\ and the newline as \n, and still use a newline to separate the name=val entries:

awk 'BEGIN{
  for(e in ENVIRON){
    v = e "=" ENVIRON[e];
    gsub(/\\/, "&&", v); gsub(/\n/,"\\n",v); print v
  }
}'
fzd$ env - $'foo\\bar\nquux=foo\\bar\nquux' lol=cat printenv
lol=cat
foo\bar
quux=foo\bar
quux

fzd$ env - $'foo\\bar\nquux=foo\\bar\nquux' lol=cat awk 'BEGIN{
  for(e in ENVIRON){
    v = e "=" ENVIRON[e];
    gsub(/\\/, "&&", v); gsub(/\n/,"\\n",v); print v
  }
}'
foo\\bar\nquux=foo\\bar\nquux
lol=cat
4
  • Thanks! I need a portable way to read, not a portable way to restore =) Commented Feb 28, 2020 at 11:12
  • 1
    @Bass please see the simplified version (no functional change) Commented Feb 28, 2020 at 11:53
  • Thanks again! Actually, what I needed was an even simpler one-liner: BEGIN { for (key in ENVIRON) { printf "%s=%s\0", key, ENVIRON[key] }} Commented Feb 28, 2020 at 16:51
  • 1
    @Bass that doesn't work with all versions of awk, unfortunately. AFAIK only GNU awk (gawk) can handle nul bytes in its data. In particular, the default awk on Debian, *BSD and busybox-based systems like OpenWRT will not print the \0. Commented Feb 28, 2020 at 16:53

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.