【问题标题】:How do I validate user input in a loop?如何在循环中验证用户输入?
【发布时间】:2021-12-07 12:07:35
【问题描述】:

我是一名学生,我需要在 Powershell ISE 中编写一个脚本,该脚本将为用户提供一个菜单,然后根据他们的选择显示操作系统信息,或者如果他们输入“q”则退出

我已经让菜单输入/输出循环正常工作,但我还需要确保他们选择了有效的选项,如果没有则重新提示。

无论用户输入的值是什么,它都会输出无效消息。

所以如果用户输入 1 就会返回:

输入无效,请从菜单中选择一个选项 @{OsName=Microsoft Windows Server 2016 标准版} 按 Enter 继续...:

我没有编程背景,所以我对 powershell 和编码的理解非常基础,大多数搜索结果都提供了超出我知识范围的示例!

function sysInfoMenu {

    param (
    [string] $Title = 'System Information'
    )

    Clear-Host

    Write-Host "=============== $Title ==============="
    "`n`n"
    Write-Host "Please select from the following options:"
    "`n"
    Write-Host "Press 1 for: OS System"
    Write-Host "Press 2 for: OS Type"
    Write-Host "Press 3 for: OS Architecture (32 or 64 bit)"
    Write-Host "Press 4 for: OS Version"
    Write-Host "Press 5 for: OS Bios Version"
    Write-Host "Press 6 for: Computer Brand"
    Write-Host "Press 7 for: Computer Name"
    Write-Host "Press 8 for: Current Domain"
    Write-Host "Press 9 for: Computer Model"
    Write-Host "Press 10 for: Current User"
    Write-Host "Press 11 for: Timezone"
    Write-Host "Press 'q' to quit."
}

do {
    sysInfoMenu
    $info = $null
    $UserInput = Read-Host "Please select an option from the menu"

        
    switch ($UserInput)
    {
      '1' {$info = Get-ComputerInfo -Property OSName}
      '2' {$info = Get-ComputerInfo -Property OSType}
      '3' {$info = Get-ComputerInfo -Property OSArchitecture}
      '4' {$info = Get-ComputerInfo -Property OSVersion}
      '5' {$info = Get-ComputerInfo -Property BiosVersion}
      '6' {$info = Get-ComputerInfo -Property CsManufacturer}
      '7' {$info = Get-ComputerInfo -Property CsName}
      '8' {$info = Get-ComputerInfo -Property CsDomain}
      '9' {$info = Get-ComputerInfo -Property CsModel}
      '10' {$info = Get-ComputerInfo -Property CsUserName}
      '11' {$info = Get-ComputerInfo -Property TimeZone}
    } 
          
          
       if ($UserInput -lt 1 -gt 11 -ne 'q'){
       Write-Host "Invalid input, please select an option from the menu"
       } 
      
  Write-Host $info
  pause
       
        
}
until ($UserInput -eq 'q') 

【问题讨论】:

    标签: powershell


    【解决方案1】:

    你有几个结构性问题。

    • 你没有终止你的函数。
    • 你没有调用你的函数。
    • 您一直调用 Get-ComputerInfo,速度很慢,只需执行一次。
    • 您的菜单需要在您的循环中,以便您可以清除屏幕并摆脱以前的答案和/或错误消息。

    这里有一些替代代码,我已对其进行评论以帮助您学习。

    function SysInfoMenu {
    
        param (
         [Parameter(Mandatory=$False)]
          [string] $Title = 'System Information'
        )
    
    #Setup:
    
       $ByeBye   = $False           #Set initial value.
       #Hide the Progress Bar. Remove line if not wanted.
       $ProgressPreference = "SilentlyContinue"
       $CompInfo = Get-ComputerInfo #You only need to call once.
    
    #Main Function Code:
    
    do {
        Clear-Host
    
        Write-Host "=============== $Title ==============="
        "`n`n"
        Write-Host "Please select from the following options:"
        "`n"
        Write-Host "Press  1 for: OS System"
        Write-Host "Press  2 for: OS Type"
        Write-Host "Press  3 for: OS Architecture (32 or 64 bit)"
        Write-Host "Press  4 for: OS Version"
        Write-Host "Press  5 for: OS Bios Version"
        Write-Host "Press  6 for: Computer Brand"
        Write-Host "Press  7 for: Computer Name"
        Write-Host "Press  8 for: Current Domain"
        Write-Host "Press  9 for: Computer Model"
        Write-Host "Press 10 for: Current User"
        Write-Host "Press 11 for: Timezone"
        Write-Host "Press 'q' to quit."
    
        $UserInput = Read-Host "Please select an option from the menu"
            
     #Note: use of Break to leave switch once match is found.
           
        switch ($UserInput) {
           '1' {$CompInfo.OSName         ;Break}
           '2' {$CompInfo.OSType         ;Break}
           '3' {$CompInfo.OSArchitecture ;Break}
           '4' {$CompInfo.OSVersion      ;Break}
           '5' {$CompInfo.BiosVersion    ;Break}
           '6' {$CompInfo.CsManufacturer ;Break}
           '7' {$CompInfo.CsName         ;Break}
           '8' {$CompInfo.CsDomain       ;Break}
           '9' {$CompInfo.CsModel        ;Break}
          '10' {$CompInfo.CsUserName     ;Break}
          '11' {$CompInfo.TimeZone       ;Break}
          'q'  {$ByeBye = $True          ;Break}
          default {"Invalid input, please select an option from the menu"}
        } #End Switch      
              
        if (-not $ByeBye) { pause }
            
      } until ($ByeBye) #Exit via $ByeBye value!
    
    } #End Function SysInfoMenu
    
    SysInfoMenu #Call your function
    

    【讨论】:

    • 非常感谢,它现在按预期工作!
    【解决方案2】:

    您的脚本几乎没问题,只是您的if 条件有些问题:

    $UserInput -lt 1 -gt 11 -ne 'q'
    

    这就是 PowerShell 评估语句的方式,以及为什么它总是进入 if 条件。使用单词 test 作为$userInput:

    'test' -lt 1   # => $false
    $false -gt 11  # => $false
    $false -ne 'q' # => $true
    

    应该是这个样子,注意-and的用法:

    'test' -lt 1 -and 'test' -gt 11 -and 'test' -ne 'q'
    

    您可以使用-notmatch 运算符的替代方法,它允许使用Regular Expressions

    在下面的示例中,$UserInput -notmatch $regex 将在任何用户输入不是我们在$validoptions 数组中看到的输入时返回$true(从111 + q)。

    $validoptions = 1..11 + 'q'
    $regex = '^{0}$' -f ($validoptions -join '$|^')
    # Regex: ^1$|^2$|^3$|^4$|^5$|^6$|^7$|^8$|^9$|^10$|^11$|^q$
    
    $waitForUSer = {
        'Press ENTER to Continue...'
        Read-Host
    }
    
    do
    {
        sysInfoMenu
        $UserInput = Read-Host "Please select an option from the menu"
        
        if ($UserInput -notmatch $regex){
            Write-Warning "Invalid input, please select an option from the menu"
            & $waitForUSer
            continue # => Go to Until, skip next lines
        }
    
        if($UserInput -eq 'q'){
            continue # => Go to Until and end the loop
        }
       
        $info = switch ($UserInput)
        {
          '1'  { 'Option 1' }
          '2'  { 'Option 2' }
          '3'  { 'Option 3' }
          '4'  { 'Option 4' }
          '5'  { 'Option 5' }
          '6'  { 'Option 6' }
          '7'  { 'Option 7' }
          '8'  { 'Option 8' }
          '9'  { 'Option 9' }
          '10' { 'Option 10' }
          '11' { 'Option 11' }
        }
          
        $info # => Show selection
        & $waitForUSer
    }
    until ($UserInput -eq 'q')
    

    【讨论】:

    • 谢谢!我从中学到了很多
    猜你喜欢
    • 2016-03-08
    • 1970-01-01
    • 2021-10-14
    • 1970-01-01
    • 2014-10-11
    • 1970-01-01
    • 2021-03-11
    • 2016-01-16
    • 2021-04-25
    相关资源
    最近更新 更多