1

OK, First I consider myself a newbie and have much to learn about PowerShell and this is my first post ever. I am trying to loop through some data and put it into a custom object and put them into separate arrays for later use. The issue is that I want to create a variable representing $week_data1 by using a counter $i so I can reduce the amount of code required. I do have a concatenated variable being written out: write-host '$week++ ='$week$i But I think it is being represented as a string? How can I get $week_data$i to represent the array to insert the data?

Input data. Each week ends on Saturday.
    $week1=@('2021-05-01')
    $week2=@('2021-05-02', '2021-05-03', '2021-05-04', '2021-05-05', '2021-05-06', '2021-05-07', '2021-05-08')
    $week3=@('2021-05-09', '2021-05-10', '2021-05-11', '2021-05-12', '2021-05-13', '2021-05-14', '2021-05-15')
    $week4=@('2021-05-16', '2021-05-17', '2021-05-18', '2021-05-19', '2021-05-20', '2021-05-21', '2021-05-22')
    $week5=@('2021-05-23', '2021-05-24', '2021-05-25', '2021-05-26', '2021-05-27', '2021-05-28', '2021-05-29')
    $week6=@('2021-05-30', '2021-05-31')
    $month =@($week1, $week2, $week3, $week4, $week5, $week6) 
    
Create the output structures to be populated.
    $week_data1=@()
    $week_data2=@()
    $week_data3=@()
    $week_data4=@()
    $week_data5=@()
    $week_data6=@()
    $month_data =@($week_data1, $week_data2, $week_data3, $week_data4, $week_data5, $week_data6)
Loop through the array and count the week number that is being processed.

    $i = 0
    foreach($week in $month)
    { $i++
    $n=0

Here I can write out a Variable and it concatenates properly.
    **write-host '$week++ ='$week$i**
        foreach($day in $week)
        {$n++
        write-host '$day ='$day
Pull in data from a .csv file to populate the custom object.
        foreach($line in $csv) 
         {
          if($line -match $day)
Match the line in the CSV file that has the correct Date in it. One line in the file per date in the month.
          { #write-host '$line.Day = ' $line.Day
            # custom object to be used later 
            $date_data = [PSCustomObject] @{
             week_numb = $i
             date = $line.Day
             attempts = $line.Attempts
             connects = $line.Connects
            }
I have tried different syntax versions but it does not work here? I want to put the custom object data into the new array for the week being processed. 
          #write-host '$week_data[$i]='$week_data[$i]
          $week_data$i += $date_data # Add data from csv file into a 
          #$week_data[$i] += $date_data
          }
         }
    
        }
    }

Issue using $week_data$i as a variable I get an error:

At line:38 char:17

  •   $week_data$i += $date_data # Add data from csv file into a
    
  •             ~~
    

Unexpected token '$i' in expression or statement. + CategoryInfo : ParserError: (:) [], ParentContainsErrorRecordException + FullyQualifiedErrorId : UnexpectedToken

mklement0
  • 312,089
  • 56
  • 508
  • 622
swampy1964
  • 13
  • 2

2 Answers2

4

You're looking for variable indirection, i.e. the ability to refer to a variable indirectly, by a name stored in another variable or returned from an expression.

Note, however, that there are usually superior alternatives, such as using arrays or hashtables as multi-value containers - see this answer for an example.

If you do need to use variable indirection, use Get-Variable and Set-Variable:

$week_data1 = 'foo', 'bar'

$i = 1

# Same as: $week_data1
# Note that "$" must NOT be specified as part of the name.
Get-Variable "week_data$i" -ValueOnly

# Same as: $week_data1 = 'baz', 'quux'
Set-Variable "week_data$i" baz, quux

# Updating an existing value requires nesting the two calls:
# Same as: $week_data1 += 'quuz'
Set-Variable "week_data$i" ((Get-Variable "week_data$i" -ValueOnly) + 'quuz')

As an aside: "extending" an array with += is convenient, but inefficient: a new array must be created behind the scenes every time - see this answer.

Similarly, calling cmdlets to set and get variables performs poorly compared to direct assignments and variable references.


As for what you tried:

  • $week_data$i = ... is an assignment expression, which is interpreted as directly juxtaposing two variables, $week_data and $i, which causes the syntax error you saw.

  • By contrast, something like Write-Output $week_data$i is a command, and while $week_data$i is also interpreted as two variable references, as a command argument it is syntactically valid, and would simply pass the (stringified) concatenation of the two variable values; in other words: $week_data$i acts as if it were double-quoted, i.e. an expandable string, and the command is therefore equivalent to Write-Output "$week_data$i"

mklement0
  • 312,089
  • 56
  • 508
  • 622
  • 1
    FYI; a few days ago, I did a PSScriptAnalizer rule request for: [`#1706` Warning if Set/Get-Variable is invoked with only the basic -Name/-Value parameters](https://github.com/PowerShell/PSScriptAnalyzer/issues/1706) – iRon Aug 30 '21 at 12:45
1

Unrelated to the answer, but likely helpful for you, I have a function that will determine what week in a month a given date is.

Function Get-Week{
[cmdletbinding()]
param([parameter(ValueFromPipeline)][string[]]$Date)
process{
    ForEach($Day in $Date){
        $DTDay=[datetime]$Day
        $Buffer = ([datetime]("{0}-01-{1}" -f $DTDay.Month,$DTDay.Year)).dayofweek.value__ -1 
        [math]::Truncate(($DTDay.Day+$Buffer)/7)+1
    }
}
}

So you feed that a string that can be converted to a date like:

'5-13-2021' | Get-Week

or

Get-Week '5-13-2021'

and you get back a number indicating what week (ending on Saturday) of the month that day falls in.

TheMadTechnician
  • 32,608
  • 2
  • 36
  • 47