1

I have 10 variables, called rows($row1, $row2, $row3...), I need the user to choose from one of this variables only knowing the right row, I'm struggling to understand how to connect text to a variable, that corrisponds to another variable and get the value, not to write it as text

$ChoosenRow = Read-Host
$rownumber = $("row" + $ChoosenRow)
$IP = Write-Output $rownumber 

If I input 10, I get $IP = row10 I'm trying to get $IP to become the value of $row10, not as a string.

Sorry for my broken english and my stupid question, I tried to search similar questions but didn't found any

Edit: iRon asked me to put more of the script:

# Carica il file e crea le variabili per il file
$FilePath = '\\ntced\CED\AssistenzaPC\IP IN GESTIONE\2021-08-16 TabellaIP.xls'
$xl = New-Object -ComObject Excel.Application
$xl.Visible = $true
$wb = $xl.Workbooks.Open($filepath)

# Prendi la prima colonna
$data = $wb.Worksheets['Foglio1'].UsedRange.Rows.Columns[1].Value2
$data2 = $wb.Worksheets['Foglio1'].UsedRange.Rows.Columns[2].Value2

# Chiudi excel aperto per prendere i dati
$wb.close()
$xl.Quit()
While([System.Runtime.Interopservices.Marshal]::ReleaseComObject($wb) -ge 0){}
while([System.Runtime.Interopservices.Marshal]::ReleaseComObject($xl) -ge 0){} 
Remove-Variable xl,wb # Rimuovi le due variabili create

# display results
$data | select -skip 1 # Rimuove il titolo sopra

# Variabili degli IP

$variables = @()
$i = 0
foreach ($row in ($data -split [Environment]::NewLine)) {
  # Crea una variabile per ogni riga
  New-Variable -Name "row$i" -Value $row
  # e un membro dell'array
  $variables += [pscustomobject]@{Name = "row$i"; Value = $row} # Copiato male, era troppo complicato arrivarci
  $i++
}

$variables2 = @()
$ii = 0
foreach ($linea in ($data2 -split [Environment]::NewLine)) {
  # Crea una variabile per ogni riga
  New-Variable -Name "linea$ii" -Value $linea
  # e un membro dell'array
  $variables2 += [pscustomobject]@{Name = "linea$ii"; Value = $linea} 
  $ii++
}

function Show-Menu
{
 param (
 [string]$Title = 'Scegli IP'
 )
 Clear-Host
 Write-Host "================ $Title ================"
 Write-Host "1: Cambia IP da tabella IP nuovi"
 Write-Host "Q: premi 'Q' per uscire."
}

Show-Menu –Title 'Scegli IP'
$selection = Read-Host 'Scegli la'

switch ($selection)
 {
     '1' {
         ' Scrivi la linea che contiene IP libero'

         $LineaScelta = Read-Host
         $rownumber = $("row" + $LineaScelta)

          $IP = Write-Output $rownumber
          $MaskBits = 20 # subnet mask in bits = 255.255.240.0
          $Gateway = "172.16.111.254"
          $Dns = "172.16.16.1"
          $IPType = "IPv4"
     } 

     'q' { 
           return
         }
 }

  # Imposta su tutte le schede di rete attive, quindi tenere acceso solo quella necessaria!
$adapter = Get-NetAdapter | ? {$_.Status -eq "up"}

# Rimuove gli IP prima di metterli 
If (($adapter | Get-NetIPConfiguration).IPv4Address.IPAddress) {
 $adapter | Remove-NetIPAddress -AddressFamily $IPType -Confirm:$false
}

If (($adapter | Get-NetIPConfiguration).Ipv4DefaultGateway) {
 $adapter | Remove-NetRoute -AddressFamily $IPType -Confirm:$false
}

 # Configura gli IP, CHE BESTEMMIE PER CAPIRE COME USARE

$adapter | New-NetIPAddress `
 -AddressFamily $IPType `
 -IPAddress $IP `
 -PrefixLength $MaskBits `
 -DefaultGateway $Gateway

# Configura il primo server DNS, non so come configurare il secondo ancora.
$adapter | Set-DnsClientServerAddress -ServerAddresses $DNS




7
  • Does this answer your question? PowerShell - Merge two variables into one Commented Aug 18, 2021 at 7:10
  • ... or do you mean something like a lookup table? Commented Aug 18, 2021 at 7:15
  • 1
    Don't worry about your English, it's good enough. Anyway, maybe you'd need an array and input is used to index it, or use a switch statement. Please edit the question and explain with more details what you'd like to do in plain English, so we can propose appropriate solution. Commented Aug 18, 2021 at 7:35
  • If I understand correctly, I think you should have a play with Get-Variable Commented Aug 18, 2021 at 8:16
  • 1
    Please try to create a minimal reproducible example and show us (in the question) how you exactly created "I have 10 variables, called rows($row1, $row2, $row3...)". Note that it is very likely that you made a wrong start, instead of creating 10 individual variables (and Get-Variable which is definitely a bad practice for this), you probably want to create an array (or a hashtable) and then use: something like $Rows[10] . Commented Aug 18, 2021 at 8:37

1 Answer 1

3

General (best practice) advice:

Don't use the <verb>-Variable cmdlets for dynamic variable names!

(Rule request: #1706 Warning if Set/Get-Variable is invoked with only the basic -Name/-Value parameters.)

Background

PowerShell (as almost all other programming languages) has an internal dictionary were it keeps all the variable names and a (direct or indirect) reference to their containing value. This dictionary (quote wikipedia),

is a data structure that implements a set abstract data type, a structure that can map keys to values. A hash table uses a hash function to compute an index, also called a hash code, into an array of buckets or slots, from which the desired value can be found. During lookup, the key is hashed and the resulting hash indicates where the corresponding value is stored.

Why not?

It is a general usage to create any (unique) variable name for a specific value, but at the moment that you find out that you start repeating yourself for a specific variable set, your program starts to become so called WET (as opposed to DRY). At this point you might come to the obvious conclusion to automate the variable names itself with statements using Set-Variable, like:

New-Variable -Name "row$i" -Value $row

To automate variables with a common purpose is definitely a good thought, but using <verb>-Variable cmdlets for this, is a bad practice as all the variables will eventually end up in the same dictionary. Therefore you might lose the oversight or even introduce conflicts with other variable names. Instead, you better create your own custom dictionary using a hashtable which is based on a similar data structure as the general variables.

How?

Instead of this:

$variables = @()
$i = 0
foreach ($row in ($data -split [Environment]::NewLine)) {
  # Crea una variabile per ogni riga
  New-Variable -Name "row$i" -Value $row
  # e un membro dell'array
  $variables += [pscustomobject]@{Name = "row$i"; Value = $row} # Copiato male, era troppo complicato arrivarci
  $i++
}

You might simply do this:

$Rows = @{}
$i = 0
foreach ($row in ($data -split [Environment]::NewLine)) { $Rows[$i++] = $Row }

And to get the specific value:

$LineaScelta = Read-Host
$IP = $Rows[[Int]$LineaScelta]

As the key of the dictionary appears to be a consecutive zero-based numeric serie, you might even simplify this further using an array:

$Rows = $data -split [Environment]::NewLine

$LineaScelta = Read-Host
$IP = $Rows[$LineaScelta]

As a side node: also try I avoid using the increase assignment operator (+=) to create a collection

Sign up to request clarification or add additional context in comments.

2 Comments

THIS IS AMAZING, first you made the code super faster and cleaner + solved my issues and teached me a lot, in just a few lines.... I was banging my head for 3 days.... Thank you so much!
@Kitsu This is a very good example why it's a good idea to include background information as well as details in the question. It's much more easy to help when we know what's actually going on.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.