57

In bash

echo ${!X*}

will print all the names of the variables whose name starts with 'X'.
Is it possible to get the same with an arbitrary pattern, e.g. get all the names of the variables whose name contains an 'X' in any position?

codeforester
  • 39,467
  • 16
  • 112
  • 140
Paolo Tedesco
  • 55,237
  • 33
  • 144
  • 193

8 Answers8

76

Use the builtin command compgen:

compgen -A variable | grep X
Johannes Schaub - litb
  • 496,577
  • 130
  • 894
  • 1,212
  • 10
    (+1) This works with local variables as well. This compgen has been today's revelation - I think I should *study* all bash builtins... – Paolo Tedesco Feb 04 '09 at 16:44
  • 2
    @AlexanderMills it works for bash. Checked with bash-3.2 on macos. – huch Sep 20 '18 at 08:35
16

This should do it:

env | grep ".*X.*"

Edit: sorry, that looks for X in the value too. This version only looks for X in the var name

env | awk -F "=" '{print $1}' | grep ".*X.*"

As Paul points out in the comments, if you're looking for local variables too, env needs to be replaced with set:

set | awk -F "=" '{print $1}' | grep ".*X.*"
diciu
  • 29,133
  • 4
  • 51
  • 68
5

Easiest might be to do a

printenv |grep D.*=

The only difference is it also prints out the variable's values.

alxp
  • 6,153
  • 1
  • 22
  • 19
3

This will search for X only in variable names and output only matching variable names:

set | grep -oP '^\w*X\w*(?==)'

or for easier editing of searched pattern

set | grep -oP '^\w*(?==)' | grep X

or simply (maybe more easy to remember)

set | cut -d= -f1 | grep X

If you want to match X inside variable names, but output in name=value form, then:

set | grep -P '^\w*X\w*(?==)'

and if you want to match X inside variable names, but output only value, then:

set | grep -P '^\w*X\w*(?==)' | grep -oP '(?<==).*'
anandi
  • 151
  • 1
  • 5
3

Enhancing Johannes Schaub - litb answer removing fork/exec in modern bash we could do

compgen -A variable  -X '!*X*'

i.e an X in any position in the variable list.

Phi
  • 735
  • 7
  • 22
1
env | awk -F= '{if($1 ~ /X/) print $1}'
dsm
  • 10,263
  • 1
  • 38
  • 72
  • I needed to get the values also. By simply removing the `$1` from your solution, my problem was solved. Thanks. – jpbochi Aug 15 '16 at 19:36
0

To improve on Johannes Schaub - litb's answer:

There is a shortcut for -A variable and a flag to include a pattern:

compgen -v -X '!*SEARCHED*'
  • -v is a shortcut for -A variable
  • -X takes a pattern that must not be matched.

Hence -v -X '!*SEARCHED*' reads as:

  • variables that do not, not match "anything + SEARCHED + anything"

Which is equivalent to:

  • variables that do match "anything + SEARCHED + anything"

The question explicitly mentions "variables" but I think it's safe to say that many people will be looking for "custom declared things" instead.

But neither functions nor aliases are listed by -v.

If you are looking for variables, functions and aliases, you should use the following instead:

compgen -av -A function -X '!*SEARCHED*'
# equivalent to:
compgen -A alias -A variable -A function -X '!*SEARCHED*'

And if you only search for things that start with a PREFIX, compgen does that for you by default:

compgen -v PREFIX

You may of course adjust the options as needed, and the official doc will help you: https://www.gnu.org/software/bash/manual/html_node/Programmable-Completion-Builtins.html

Romain Vincent
  • 2,875
  • 2
  • 22
  • 29
0

to expand Phi's and Johannes Schaub - litb's answers for the following use case:

print contents of all environment variables whose names match a pattern as strings which can be reused in other (Bash) scripts, i.e. with all special characters properly escaped and the whole contents quoted

In case you have the following environment variables

export VAR_WITH_QUOTES=\"FirstName\ LastName\"\ \<firstname.lastname@example.com\>
export VAR_WITH_WHITESPACES=" 
    a bc
"
export VAR_EMPTY=""
export VAR_WITH_QUOTES_2=\"\'

then the following snippet prints all VAR* environment variables in reusable presentation:

for var in $(compgen -A export -X '!VAR*'); do
  printf "%s=%s\n" "$var" "${!var@Q}"
done

Snippet is is valid for Bash 4+.

The output is as follows, please note output for newlines, empty variables and variables which contain quotation characters:

VAR_EMPTY=''
VAR_WITH_QUOTES='"FirstName LastName" <firstname.lastname@example.com>'
VAR_WITH_QUOTES_2='"'\'''
VAR_WITH_WHITESPACES=$' \n\ta bc\n'

This also relates to the question Escape a variable for use as content of another script

maoizm
  • 682
  • 13
  • 17