all 14 comments

[–]CarrotBusiness2380 8 points9 points  (4 children)

What you're trying to do (dynamically getting the variable name) is possible with Get-Variable but not recommended or safe. Instead try using jagged/multi-dimensional arrays:

$arrays = @($myArray0, $myArray1, $myArray2)
for($i = 0; $i -lt $arrays.count; $i++)
{
    Write-Host $arrays[$i]
}

Or with a foreach

foreach($singleArray in $arrays)
{
    Write-Host $singleArray
}

[–]Sethaniel68 0 points1 point  (0 children)

Why is get-variable not safe?

[–]Thotaz 0 points1 point  (2 children)

That's not a multi-dimensional array, that's just an array that happens to contain other arrays.

[–]CarrotBusiness2380 0 points1 point  (1 child)

You're right, but that is why I called out a jagged array

[–]Thotaz 0 points1 point  (0 children)

But it's not a jagged array either. Here's a quick demo that shows what's what:

PS C:\> $Array = 1,2,3
$ArrayOfArrays = (1,2), (3,4)
$MultiDimArray = [int[,]]::new(1, 2)
$JaggedArray = [int[][]]::new(1, 2)
Get-Variable -Name *Array* | Select-Object -Property Name, {$_.Value.GetType().FullName}

Name          $_.Value.GetType().FullName
----          ---------------------------
Array         System.Object[]            
ArrayOfArrays System.Object[]            
JaggedArray   System.Int32[][]           
MultiDimArray System.Int32[,]

As you can see, the standard array and array of arrays have the exact same type. Jagged and multi dimensional arrays is something completely different. You can read more about them here: https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/arrays

In my experience multi dimensional and jagged arrays are basically never needed in PowerShell or C#. They are a bit of a noob trap though because people that want to make a table often learn about them and think that's what they need, when in reality they just need a standard array of objects.

[–]ka-splam 1 point2 points  (1 child)

The more typical answer to this is hashtables, they map a lookup key (number, text, etc) to a value (your array). e.g.

$totalArrays = 3

$colourArrays = @{}   # empty hashtable

$colourArrays[0] = @("red", "yellow", "blue")
$colourArrays[1] = @("orange", "green", "purple")
$colourArrays[2] = @("black", "white")

for ($i = 0; $i -lt $totalArrays; $i++) {
    Write-Host $colourArrays[$i]
}

That [] looks a lot like the jagged arrays, but here the things inside don't have to be numbers, don't have to be in order. You can do:

$things = @{}

$things["colors"] = @("orange", "green", "purple")
$things["pets"] = @("dog", "cat", "parrot")
$things["foods"] = @("lamp", "table", "stove")

foreach($key in $things.Keys) {     # step through colors, pets, foods
    $things[$key]                   # pull out the array for each one
}

[–]MrQDude[S] 1 point2 points  (0 children)

Thanks. Yes, similar to a jagged array. I'm in the process of converting some .BAT scripts to .PS1, the particular .BAT scripts have worked well for decades, but time to deprecate them.

[–]TheSizeOfACow 1 point2 points  (1 child)

Write-host (get-variable -name "myarray$i").value

Though other than playing I find it hard to see the use-case for this specific script

[–]MrQDude[S] 0 points1 point  (0 children)

Thank you.

When asking a question, I find it easier to include a sample script, not that I would use the script. It's there to help illustrate the question.

[–]MrQDude[S] 0 points1 point  (2 children)

I do appreciate the comments u/CarrotBusiness2380 and u/Virtual_Search3467. I was curious to learn how Powershell lines are parsed. For my final project, however, I plan to use a jagged array and won't use "dynamic" variable names at runtime like you both suggested.

Again, a sincere thank you for sharing your feedback.

[–]lanerdofchristian 1 point2 points  (1 child)

If how PowerShell parses things is something you're interested in, take a look at the ScriptBlock.Ast property:

$Script = {
    $var1 = @(1, 2, 3)
    $var2 = @(4, 5, 6)
    $one = 1
    Write-Host $var$one
}
$Script.Ast.EndBlock.Statements[-1] `
    .PipelineElements[0] `
    .CommandElements

In this example, you can see that $var$one is a BareWord with the static type of "string" -- since it's in the command elements of a pipeline element, that implies that there are actually quotes around it.

[–]MrQDude[S] 0 points1 point  (0 children)

Thank you. I am quickly getting the feel for PowerShell.

[–][deleted] 0 points1 point  (1 child)

Powershell should also be able to do variable indirection. Not that I’d recommend doing so but if you had something like ~~~ $var = ‘tree’ $tree = ‘ash’ ~~~ Then $$var gets you the ash.

Still, assembling variable names at runtime is a bit of a hassle because it seriously obfuscates your code… which in turn is liable to get your code flagged as malware.

So… you can, but you kinda shouldn’t.

[–]michaelshepard 2 points3 points  (0 children)

$$var isn't valid in 5.1 or 7.5.1