3
votes

Comment faire d'une variable une plage dans PowerShell?

J'essaie de rendre une variable égale à une plage. Mon script inclut une entrée utilisateur et cette entrée doit se situer dans une certaine plage. J'utiliserai la plage plusieurs fois dans le script, je veux donc que ce soit une variable. Voici ce que j'ai essayé:

     #user input for how many servers will be tested
     $numofservers = Read-Host -Prompt "How many servers are being tested?"
     if($numofservers -eq $serverrange) {
     "Proceed"
     } 
     else {
     "Server limit exceeded"
      }

et j'ai essayé

    $serverrange = 1..18

Je l'ai googlé mais je ne trouve pas grand-chose sur ce. Le problème est que PowerShell ne voit pas cela comme une plage, il la voit littéralement comme 1..18. Donc, si je fais Write-Output $ serverrange, il s'affiche comme "1..18". Ma question est donc de savoir comment puis-je lui faire voir une plage ou comment modifier le script pour incorporer la plage? Voici le reste du script:

    $serverrange = "1..18"

Edit: Je n'ai pas réalisé que $ serverrange = 1..18 fonctionnait.


5 commentaires

mettre la plage entre guillemets en fait une chaîne . [ grin ] aussi, le cal Read-Host renvoie ... une chaîne . votre 2ème exemple donne une plage appropriée, essayez de tester les $ Variables en utilisant $ VarName.GetType () pour voir ce qu'il y a dans la variable.


Quel type de .net avez-vous en tête? Le .Net a-t-il un type de «plage» comme certaines autres plates-formes / langages?


@Lee_Dailey, merci pour la réponse. Je ne savais pas que la deuxième option fonctionnait, ma mauvaise. Savez-vous comment je peux faire en sorte que l'entrée utilisateur affiche "Poursuivre" si elle se situe dans cette plage?


@ techguy1029 - votre test est pour $ ServerLimit mais je ne vois pas où vous le définissez. si vous voulez voir si $ numofservers est dans la plage, forcez-le à un [int] puis utilisez $ numofservers -in $ serverrange .


Ça a marché! Merci


3 Réponses :


1
votes

Si vous avez une chaîne "1..18", vous pouvez utiliser invoke-expression pour l'évaluer, par exemple:

PS C:\Users\chris> $s = "1..18"
PS C:\Users\chris> $s
1..18
PS C:\Users\chris> $r = invoke-expression $s
PS C:\Users\chris> $r
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
PS C:\Users\chris>


3 commentaires

Merci pour plus d'informations. Comment faire pour que le script accepte la plage? Si j'entre un nombre dans la plage autre que 1, j'obtiens le deuxième message au lieu du premier.


Vous pouvez utiliser -contains , par exemple $ x = "2"; if (1..18 -contient $ x) {"Gotcha"} .


Pendant que votre solution techniquement fonctionne, Invoke-Expression est à éviter : c'est rarement le bon outil et présente des risques de sécurité.



1
votes

Cela fonctionne pour moi:

> $p = 1..18
> $p
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
>

En utilisant: PSVersion 5.1.14393.1944


0 commentaires

4
votes

Comme vous vous en êtes rendu compte depuis, une expression sans guillemets telle que 1..18 fonctionne parfaitement : elle utilise PowerShell opérateur de plage ( .. ) pour créer un tableau d'entiers contigus de 1 à 18 ; c'est-à-dire, c'est l'équivalent du tableau suivant literal :

# Define the implied lower bound and the maximum upper bound.
$lowerBound = 1
$maxUpperBound = 18

# Prompt the user for the upper bound of the range, with validation,
# until a valid value is entered.
do {
  $userInput = Read-Host -Prompt "How many servers are being tested?"
  if (
    ($upperBound = $userInput -as [int]) -and 
    ($upperBound -ge $lowerBound -and $upperBound -le $maxUpperBound)
  ) {
    break # valid value entered, exit loop.
  } else {
    # Invalid input: Warn, and prompt again.
    Write-Warning "'$userInput' is either not a number or is outside the expected range of [$lowerBound,$maxUpperBound]."
  }
} while ($true)

# Create the array of indices based on user input.
1..$upperBound

En revanche, "1..18" est une chaîne (extensible) dont le contenu s'imprime tel quel (littéral 1..18 , dans ce cas, car la chaîne ne contient ni références de variables ni sous-expressions) .

Important : Bien que cela fonctionne techniquement , utilisez Invoke-Expression pour évaluer un string comme une instruction PowerShell (par exemple, Invoke-Expression "1..18" ), cette approche doit être évité : Invoke-Expression est rarement le bon outil et présente un risque de sécurité fort >, en particulier avec une entrée utilisateur non assainie - voir le billet de blog de l'équipe PowerShell intitulé "Invoke-Expression considéré comme dangereux" .

Votre défi semble être de créer une telle plage en fonction de l ' entrée de l'utilisateur , qui est par défaut une chaîne , comme renvoyé par Read-Host.

L ' opérateur de plage est capable de convertir dynamiquement l'un ou l'autre des opérandes (extrémité de plage) en un entier et accepte volontiers les expressions comme points de terminaison de la plage :

1
2
3

Si vous entrez 3 code> (qui, comme indiqué, est renvoyé sous forme de chaîne ), PowerShell convertit dynamiquement cette chaîne en son équivalent entier et crée le tableau 1..3 , dont la sortie par défaut ressemble comme ceci:

1..(Read-Host 'Enter the upper bound') 

Cela dit, afin de (a) fournir une invite conviviale qui (b) applique une plage prédéfinie d'entrées (nombres), plus du travail est nécessaire .

Par conséquent:

  • Assurez-vous que ce que l'utilisateur entre peut être converti en (a) un nombre qui (b) se situe dans la plage attendue; sinon, demandez à nouveau.

  • Une fois qu'une entrée valide a été reçue, utilisez l'opérateur de plage de PowerShell ( .. ) pour construire le tableau d'indices, comme vous le souhaitez.

 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18


3 commentaires

Oui, j'ai recherché sur Google ce que vous avez dit et je souhaite également vous expliquer pourquoi Invoke-Expression n'est pas très sécurisé. C'est intéressant. En tant qu'utilisateur de PowerShell nouveau, je n'avais aucune idée. community.idera. com / database-tools / powershell / powertips / b / ti‌ ps /…


Donc, si Invoke-Expression n'est pas la solution, comment suggéreriez-vous de gérer les plages extraites d'un fichier texte ( exemple )? Y a-t-il une alternative, par ex. "1..10" -as [???] ou un moyen d'avoir par exemple Get-Content interpréter les chaînes comme des plages ou des entiers?


@FatalBulletHit [int] $ from, [int] $ to = "1..10" -split '\. \.'; $ de .. $ à