Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Loop over environment variables in POSIX sh

I need to loop over environment variables and get their names and values in POSIX sh (not bash). This is what I have so far.

#!/usr/bin/env sh

# Loop over each line from the env command
while read -r line; do
  # Get the string before = (the var name)
  name="${line%=*}"
  eval value="\$$name"

  echo "name: ${name}, value: ${value}"
done <<EOF
$(env)
EOF

It works most of the time, except when an environment variable contains a newline. I need it to work in that case.

I am aware of the -0 flag for env that separates variables with nul instead of newlines, but if I use that flag, how do I loop over each variable? Edit: @chepner pointed out that POSIX env doesn't support -0, so that's out.

Any solution that uses portable linux utilities is good as long as it works in POSIX sh.

like image 483
Justin Howard Avatar asked Jan 27 '17 16:01

Justin Howard


People also ask

How do I iterate over a range of numbers defined by variables in bash?

You can iterate the sequence of numbers in bash in two ways. One is by using the seq command, and another is by specifying the range in for loop. In the seq command, the sequence starts from one, the number increments by one in each step, and print each number in each line up to the upper limit by default.

What is the difference between Env and Printenv?

The difference between printenv and env command is that they have their own unique feature. For printenv , we can ask it to give value of a particular environment variable. For env , it has more function — set environment and execute command.

Which are the correct syntax to iterate over 10 numbers in shell scripting?

We want to run certain commands by using the “for” loop for up to 10 iterations. The “for” uses simple brackets as the first syntax and specifies the condition in it. The loop's start value is “1” as per the iterator “I”. It will continue to run until the iterator value becomes less than or equivalent to 10.


1 Answers

There is no way to parse the output of env with complete confidence; consider this output:

bar=3
baz=9

I can produce that with two different environments:

$ env -i "bar=3" "baz=9"
bar=3
baz=9
$ env -i "bar=3
> baz=9"
bar=3
baz=9

Is that two environment variables, bar and baz, with simple numeric values, or is it one variable bar with the value $'3\nbaz=9' (to use bash's ANSI quoting style)?


You can safely access the environment with POSIX awk, however, using the ENVIRON array. For example:

awk 'END { for (name in ENVIRON) {
            print "Name is "name;
            print "Value is "ENVIRON[name];
           }
         }' < /dev/null

With this command, you can distinguish between the two environments mentioned above.

$ env -i "bar=3" "baz=9" awk 'END { for (name in ENVIRON) { print "Name is "name; print "Value is "ENVIRON[name]; }}' < /dev/null
Name is baz
Value is 9
Name is bar
Value is 3
$ env -i "bar=3
> baz=9" awk 'END { for (name in ENVIRON) { print "Name is "name; print "Value is "ENVIRON[name]; }}' < /dev/null
Name is bar
Value is 3
baz=9
like image 119
chepner Avatar answered Nov 15 '22 08:11

chepner