2

Say I have the following environment variables:

a = Poke
b = mon
Pokemon= Feraligatr

I want to be able to concatenate a and b environment variables to get the variable name Pokemon and the get Pokemon value like $($env:ab) or $($env:$($env:a)$($env:b)) (This examples does not work)

mklement0
  • 382,024
  • 64
  • 607
  • 775
Retrosec6
  • 169
  • 11
  • What do environment variables do in your code? Read [this](https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_environment_variables?view=powershell-7.3) article please. What you want to do requires [reflection](https://blog.ironmansoftware.com/daily-powershell/dotnet-reflection-powershell/). Please explain WHY exactly you want to do this. What is the purpose of your code. –  Feb 16 '23 at 17:07
  • 1
    Does this answer your question? [Get the value of an environment variable whose name is stored in a variable](https://stackoverflow.com/questions/69311346/get-the-value-of-an-environment-variable-whose-name-is-stored-in-a-variable) The answer is `(Get-Item -Path env:\$(($env:a)+($env:b))).Value` – JosefZ Feb 16 '23 at 17:21
  • @Max They do not do anything special, they are just two (`a` and `b`) strings passed as parameters and set as environment variables, in order to the get `Pokemon` environment variable I need to concatenate this two first and key try to get the variable value, – Retrosec6 Feb 16 '23 at 17:22
  • 2
    The sub-expressions are not needed. Simply do `(Get-Item env:$env:a$env:b).Value`. This is easier to read in an editor that does proper syntax highlighting. Alternatively `(Get-Item env:"$env:a$env:b").Value` – zett42 Feb 16 '23 at 17:47
  • That code isn't powershell. – js2010 Feb 17 '23 at 21:25

1 Answers1

1

Building on the helpful comments:

You're looking for indirection, i.e. the ability to refer to an environment variable indirectly, via another (environment) variable(s) storing the target variable's name.


PowerShell-idiomatic solution:

Use the Env: drive in combination with the Get-Content cmdlet:

# The target environment variable.
$env:Pokemon='bingo!'

# The variables that, in combination, return the *name* 
# of the target environment variable.
$env:a = 'Poke'
$env:b = 'mon'

# Use Get-Content and the env: drive to retrieve
# an environment variable by an *indirectly* specified name.
# Note: 
#   * env:$env:a$env:b is treated like "env:$env:a$env:b",
#     i.e. an expandable (interpolating string).
#   * For better visual delineation of the variables, use:
#       env:${env:a}${env:b}
#   * `-ErrorAction Ignore` ignores the case when the target var.
#     doesn't exist (quietly returns $null`)
# -> 'bingo!'
Get-Content -ErrorAction Ignore env:$env:a$env:b 

# Alternative, with explicit string concatenation.
Get-Content -ErrorAction Ignore ('env:' + $env:a + $env:b)

Note:

  • To set environment variables indirectly, use the Set-Content cmdlet; e.g.:

    $varName = 'FOO'
    Set-Content env:$varName BAR # $env:FOO now contains 'BAR'
    
  • Applying the same technique to regular shell variables (non-environment variables), requires either use of the variable: drive, or, for more flexibility, the Get-Variable and Set-Variable cmdlets - see this answer.

  • More more information about expandable (interpolating) string literals such as "env:$env:a$env:b", see the conceptual about_Quoting help topic.


.NET API alternative:

As Max points out, you can also use the static System.Environment.GetEnvironmentVariable .NET method:

[Environment]::GetEnvironmentVariable("${env:a}${env:b}")

For more information about calling .NET API methods from PowerShell, see the conceptual about_Methods help topic.

mklement0
  • 382,024
  • 64
  • 607
  • 775
  • Can't you just use the following in powershell? `[Environment]::GetEnvironmentVariable("$($env:a)$($env:b)")`. That should work as long as the variables already exist, right? –  Feb 17 '23 at 10:16
  • @Max, yes, good point, thanks - I've added your suggestion to your answer. – mklement0 Feb 17 '23 at 15:16