PowerShell脚本菜单选择项追加字符串而非数组新条目问题
PowerShell菜单选项数组被意外转为字符串的问题解决
问题根源
你遇到的核心问题是PowerShell的自动类型拆箱行为:当使用Where-Object过滤数组时,如果过滤结果仅包含单个元素,PowerShell会自动将数组转换为单个字符串值,而非保留数组类型。后续再用+=添加元素时,会执行字符串拼接而非数组追加,最终出现"Option 1Option 3"这类错误结果。
举个例子:
- 初始
$choice是数组@("Option 1", "Option 2") - 删除其中一个选项后,过滤结果是单个字符串
"Option 1",而非数组@("Option 1") - 此时再执行
$choice += "Option 3",就会变成字符串拼接,得到"Option 1Option 3"
解决方案
方案1:强制保持数组类型
在每次使用Where-Object过滤后,用@()包裹结果,强制将输出转为数组类型,避免自动拆箱。修改所有删除选项的代码块:
# 原删除逻辑 $choice = $choice | Where-Object {$_ -ne "Option 1"} # 修改后,强制转为数组 $choice = @($choice | Where-Object {$_ -ne "Option 1"})
方案2:使用ArrayList存储选择
改用System.Collections.ArrayList存储选中项,它不会触发自动拆箱,操作更稳定:
- 初始化时替换数组声明:
$choice = New-Object System.Collections.ArrayList - 添加元素用
Add()方法:[void]$choice.Add("Option 1")([void]用于抑制Add方法返回的索引值) - 删除元素用
Remove()方法:$choice.Remove("Option 1")
修改后的完整脚本(方案1版本)
# Set the initial choices $choice = @() # Use a while loop to keep the menu open until the user selects the "Exit" option while ($true) { # Clear the screen Clear-Host # Use a foreach loop to display each menu option, including an asterisk on the selected options foreach ($option in "Option 1", "Option 2", "Option 3", "Option 0", "Exit") { if ($choice -contains $option) { Write-Host "$option *" } elseif ($option -eq "Option 0") { # "Option 0" is not a selectable option, so always display it as deselected Write-Host $option } else { Write-Host $option } } # Prompt the user to enter their selection $userInput = Read-Host "Enter your selection" # Use a switch statement to execute the selected options switch -regex ($userInput) { "0" { # Code for Option 0 # Print the selected options and exit the script Write-Warning "Choices variable: $choice" Write-Host "Selected options: " switch ($choice) { "Option 1" { Write-Host "1" } "Option 2" { Write-Host "2" } "Option 3" { Write-Host "3" } default { Write-Host "No selected options." } } # Return to exit the current iteration of the while loop return } "1" { # Code for Option 1 # Check if the user has already selected this option if ($choice -contains "Option 1") { # Remove the option from the $choice variable, force array type $choice = @($choice | Where-Object {$_ -ne "Option 1"}) } else { # Add the option to the $choice variable $choice += "Option 1" } } "2" { # Code for Option 2 # Check if the user has already selected this option if ($choice -contains "Option 2") { # Remove the option from the $choice variable, force array type $choice = @($choice | Where-Object {$_ -ne "Option 2"}) } else { # Add the option to the $choice variable $choice += "Option 2" } } "3" { # Code for Option 3 # Check if the user has already selected this option if ($choice -contains "Option 3") { # Remove the option from the $choice variable, force array type $choice = @($choice | Where-Object {$_ -ne "Option 3"}) } else { # Add the option to the $choice variable $choice += "Option 3" } } "4" { # Code for Exit # Break out of the while loop to end the script break } default { # Code for invalid selection or deselection # Check if the user has deselected an option if ($choice -contains $userInput) { # Remove the option from the $choice variable, force array type $choice = @($choice | Where-Object {$_ -ne $userInput}) } else { # The user has entered an invalid selection Write-Host "Invalid selection" } } } }
内容的提问来源于stack exchange,提问作者SignalRaptor
相关产品推荐
相关产品推荐

