Help needed - UNIX command

The 'env' command prints out all of the environment variables and their values.
Come up with a command that prints a list of environment variables whose names
end with either 'NAME', 'DIR' or 'PATH'.

What I've tried.


$ env | grep '[NAME, DIR, PATH]'

Although it highlights the part of the variables it does not list them as it should. It actually prints the whole lines including the variables. Not sure what I'm missing.

University Of Technology Sydney, Unix Systems Programming

Hello edujs7,

Could you please try following.

env | awk 'BEGIN{FS="="} $1 ~ /.*(NAME$|DIR$|PATH$)/'

Thanks,
R. Singh

1 Like

Try:

env | grep -E '^(NAME|DIR|PATH)='

This gives me the below; seems to be only picking up "PATH=" and nothing else.


$ env | egrep '^(NAME|DIR|PATH)='

PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin

--- Post updated at 04:06 AM ---

Thank you RavinderSingh13

I get the below output - however, I believe I only need the Variables listed and nothing else.

env | awk 'BEGIN{FS="="} $1 ~ /.*(NAME$|DIR$|PATH$)/'

USERNAME=eduardo
MANDATORY_PATH=/usr/share/gconf/ubuntu.mandatory.path
TEXTDOMAINDIR=/usr/share/locale/
DEFAULTS_PATH=/usr/share/gconf/ubuntu.default.path
WINDOWPATH=2
LOGNAME=eduardo
XDG_RUNTIME_DIR=/run/user/1000
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin

Hello edujs7,

In case you want to have only variable names then try following.

env | awk 'BEGIN{FS="="} $1 ~ /.*(NAME$|DIR$|PATH$)/{print $1}'

Thanks,
R. Singh

1 Like

In a regular expression (RE) the ^ means the beginning of the line; together with the = it enforces an exact match. Omit the ^ and it must only end with the given pattern.

$1 ~ /.*(NAME$|DIR$|PATH$)/ is correct, because the $1 field is = delimited, and in a RE the $ enforces the end of the field. The .* means any characters but is not needed here because any leading characters are always permitted in a RE (unless there is a ^ anchor). So it is optimized $1 ~ /NAME$|DIR$|PATH$/ or with a common $ anchor $1 ~ /(NAME|DIR|PATH)$/ .

1 Like

Thanks so much - that worked :slight_smile:

Sorry to be a pain but would you please be able to explain what the actual command does :smiley: - and wouldn't egrep work for this?

We already did. The BEGIN block, running before everything else, sets the field separator as =. Then the expression tells AWK to print all lines where the first field, $1, matches the given regex.

You could, kind of, sort of use grep, depending on if your system has egrep for all the bits and pieces that made solving the problem in awk easy; but even if you have extended support, it would be more awkward since it doesn't have columns like awk does. Why not use a tool that has all the right things available by default and is much simpler to use?

1 Like

Assuming that you have submitted you homework by now... and expanding a bit on what Corona688 already said...

The command:

env | awk -F= '$1 ~ /(NAME|DIR|PATH)$/{print $1}'

tells awk to read the output produced by env , to split each line it reads into fields separated by the = character, and then look at the first field in each line. If, and only if, that first field ends with one of the three strings you're looking for, it prints the contents of the first field on that line. It then goes on to process the next line of input from env .

You could come close to what you want with egrep using:

env | egrep -o '^[!=]*(NAME|DIR|PATH)=' 

which with my current environment would give you:

CDPATH=
LOGNAME=
PATH=
TMPDIR=
XPC_SERVICE_NAME=

but then you would have to post-process the output to get rid of the = that you don't want to print. You could easily do that with a second grep or egrep , but it is much more efficient to invoke awk once instead of egrep and another grep or egrep .

If you do decide to use two grep s instead of awk , note that you can do it with two invocations of grep without using egrep at all (and grep is frequently slightly smaller and faster than egrep , but this can vary from operating system to operating system):

env | grep -o '^[^=]*' | grep -e 'NAME$' -e 'PATH$' -e 'DIR$'
CDPATH
LOGNAME
PATH
TMPDIR
XPC_SERVICE_NAME

In the above, the first grep throws away everything on each line starting with the first = found on each line of output from env and the second grep throws away any lines that don't end with one of the three strings you're searching for.