4

I have some variables that i need to get the value from, the thing is that in the middle of the name i can have any possible value because it's the artifacts name.

Example: I have these environment variables: RELEASE_ARTIFACTS__TESTECOMPLETEPR__PROJECTNAME RELEASE_ARTIFACTS__TESTECOMPLETEPR_REPOSITORY_NAME

And i need something like: $repoId = (Get-Item -Path Env:RELEASE_ARTIFACTS_*_REPOSITORY_ID).Value or $repoId = $Env:RELEASE_ARTIFACTS_*_REPOSITORY_ID

But the * doesn't seem to work. How can i do this?

wolfdebs
  • 153
  • 7

1 Answers1

4

Wildcard expressions are supported, with all providers, in the -Path parameter of the Get-Item cmdlet, and also with Get-Content, which is preferable here because it returns the environment-variable value directly (no need for (...).Value); to demonstrate:

$env:RELEASE_ARTIFACTS_FOO_REPOSITORY_ID = 1

Get-Content env:RELEASE_ARTIFACTS_*_REPOSITORY_ID # -> 1

Perhaps surprisingly, they are also supported when you use namespace variable notation, though you must then enclose the reference in {...} (because a * would otherwise not be recognized as part of a variable name):

${env:RELEASE_ARTIFACTS_*_REPOSITORY_ID} # -> 1

Caveats:Tip of the hat to Daniel.

  • If the wildcard pattern matches multiple items (environment variables in this case), a statement-terminating error occurs. Use the Get-Content (or Get-Item) approach to retrieve multiple values (items).

    • Given this awkwardness, along with the escaping pitfalls discussed below, it would make sense not to support wildcard matching in namespace variable notation, as suggested in GitHub issue #9225; while technically a breaking change, my sense is that not much real-world code would be impacted.
  • Strangely, namespace variable notation with wildcard patterns does not work with variables (where the notation is rarely used to begin with, however, given that $variable:foo offers no advantage over $foo): ${variable:HOM*} performs no wildcard matching and behaves like an undefined variable (it quietly evaluates to $null by default).

    • While the Get-Content / Get-Item approach does work, note that there's also a dedicated Get-Variable cmdlet (use -ValueOnly to get just the value) - e.g. Get-Variable HOM* -ValueOnly - which additionally supports accessing variables in different scopes, via the -Scope parameter.

Namespace variable notation vs. Get-Content:

  • Namespace variable notation is both more concise and performs better (because a cmdlet call isn't involved).

  • However, the Get-Content approach is sometimes required, namely when you use a variable to specify the environment-variable name or name pattern; that is, assuming variable definition $envVarName = 'RELEASE_ARTIFACTS_*_REPOSITORY_ID':

    • ${env:$envVarName} does not work,
    • but Get-Content env:$envVarName does.
  • Escaping pitfalls:

    • Escaping wildcard metacharacters such as [ that you want to be interpreted verbatim is currently challenging, due to the bugs discussed in this answer.

    • If the whole name should be used verbatim, you can avoid the need for escaping by using Get-Content's -LiteralPath parameter instead; however, this isn't an option with namespace variable notation, where names are invariably treated as wildcard patterns.

mklement0
  • 382,024
  • 64
  • 607
  • 775
  • 1
    Thank you, @Daniel - excellent points. I've added the info to the answer, with some extra commentary. `${variable:PSVer*Table}` not working is at the very least a strange inconsistency, though in the grand scheme of things I think it would have been wiser never to support wildcard matching in namespace variable to begin with; that is, `${env:someName}` should always have been the equivalent of `Get-Content -LiteralPath env:someName`, not `Get-Content `-Path env:someName` - that also solves the awkwardness of the error occurring with _multiple_ matches - see the linked GitHub issue. – mklement0 Aug 06 '21 at 19:44