0

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




iRon
  • 14,879
  • 7
  • 40
  • 67
Kitsu
  • 3
  • 2
  • Does this answer your question? [PowerShell - Merge two variables into one](https://stackoverflow.com/questions/68822619/powershell-merge-two-variables-into-one) – Olaf Aug 18 '21 at 07:10
  • ... or do you mean something like a lookup table? – Olaf Aug 18 '21 at 07: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. – vonPryz Aug 18 '21 at 07:35
  • If I understand correctly, I think you should have a play with `Get-Variable` – mjsqu Aug 18 '21 at 08:16
  • 1
    Please try to create a [mcve] 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](https://docs.microsoft.com/powershell/module/microsoft.powershell.core/about/about_hash_tables)) and then use: something like `$Rows[10]` . – iRon Aug 18 '21 at 08:37
  • So, I have a table in excel with 2 columns, one with IP addresses, and one with a mac addreses if the IP is taken, I want to make a script that takes the IP, and based on user choice will set the IP configuration to the machine, I need to take IPs from there since they are managed by the network manager not me, so I don't know which ones he will place there. iRon, I think you gave me the right track to follow (hashtable/array), instead of using a single variable for every row in the file... I fell in love with powershell, but am noob... I edited the answer and put the whole (horrible) thing. – Kitsu Aug 18 '21 at 08:57
  • @vonPryz I commented a better explanation and put the complete script, it's my first script / use of powershell so I know it's pretty bad. – Kitsu Aug 18 '21 at 09:10

1 Answers1

1

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. The dictionary is based on a binary search algorithm to be able to quickly find the value related to the specific variable name.

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 your program isn't anymore DRY and starting to automate the variable names itself with statements using Set-Variable, like: New-Variable -Name "row$i" -Value $row, 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 also based on a binary search).

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

iRon
  • 14,879
  • 7
  • 40
  • 67
  • 1
    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 Aug 18 '21 at 11:10
  • 1
    @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. – vonPryz Aug 18 '21 at 15:55