gpt4 book ai didi

powershell - 将单个以空格分隔的字符串作为多个参数传递

转载 作者:行者123 更新时间:2023-12-03 01:09:14 25 4
gpt4 key购买 nike

我有一个Powershell功能,在该功能中,我试图允许用户通过键入单词“add”或“remove”,然后以空格分隔的项目列表来从列表中添加或删除项目。我在下面有一个示例(略作编辑,因此您可以将代码放入powershell提示符中以对其进行“实时”测试)。

$Script:ServerList = @("Server01","Server02","Server03")
Function EditServerList (){
$Script:ServerList = $Script:ServerList |Sort -Unique
Write-host -ForegroundColor Green $Script:ServerList
$Inputs = $args
If ($Inputs[0] -eq "start"){
$Edits = Read-Host "Enter `"add`" or `"remove`" followed by a space-delimited list of server names"
#"# EditServerList $Edits
# EditServerList $Edits.split(' ')
EditServerList ($Edits.split(' ') |Where {$_ -NotLike "add","remove"})
EditServerList start
} Elseif ($Inputs[0] -eq "add"){
$Script:ServerList += $Inputs |where {$_ -NotLike $Inputs[0]}
EditServerList start
} Elseif ($Inputs[0] -eq "remove"){
$Script:ServerList = $Script:ServerList |Where {$_ -NotLike ($Inputs |Where {$_ -Notlike $Inputs[0]})}
EditServerList start
} Else {
Write-Host -ForegroundColor Red "ERROR!"
EditServerList start
}
}
EditServerList start

如您所见,该函数接受一个参数列表。第一个参数在If / Then语句中求值,然后其余参数被视为要在列表中添加或删除的项目。

我尝试了几种不同的方法,您可以在第一次IF评估中看到这些注释。

我有两个问题。
  • 当我放入“add Server05 Server06”(不带引号)之类的内容时,它可以工作,但它也会加入“add”一词。
  • 当我放入“删除Server02 Server03”(不带引号)时,它根本不会编辑数组。

  • 谁能指出我要去哪里了,或者提出更好的解决方案?

    最佳答案

    要预先解决标题的一般性问题,请执行以下操作:

  • 当您将数组传递给函数(别无其他)时,$Args接收包含整个数组的单个参数,因此您必须使用$Args[0]来访问它。
  • 有一种方法可以使用splatting将数组作为单个参数传递,但是它需要一个中间变量-参见底部。
  • 为避免此类问题引起混淆,请正式声明您的参数。


  • 请尝试以下操作:
    $Script:ServerList = @("Server01", "Server02", "Server03")

    Function EditServerList () {
    # Split the arguments, which are all contained in $Args[0],
    # into the command (1st token) and the remaining
    # elements (as an array).
    $Cmd, $Servers = $Args[0]
    If ($Cmd -eq "start"){
    While ($true) {
    Write-host -ForegroundColor Green $Script:ServerList
    $Edits = Read-Host "Enter `"add`" or `"remove`" followed by a space-delimited list of server names"
    #"# Pass the array of whitespace-separated tokens to the recursive
    # invocation to perform the requested edit operation.
    EditServerList (-split $Edits)
    }
    } ElseIf ($Cmd -eq "add") {
    # Append the $Servers array to the list, weeding out duplicates and
    # keeping the list sorted.
    $Script:ServerList = $Script:ServerList + $Servers | Sort-Object -Unique
    } ElseIf ($Cmd -eq "remove") {
    # Remove all specified $Servers from the list.
    # Note that servers that don't exist in the list are quietly ignored.
    $Script:ServerList = $Script:ServerList | Where-Object { $_ -notin $Servers }
    } Else {
    Write-Host -ForegroundColor Red "ERROR!"
    }
    }

    EditServerList start
  • 注意如何在"start"分支内使用循环,以避免耗尽堆栈空间,如果继续递归,可能会发生这种情况。
  • $Cmd, $Servers = $Args[0]将参数数组(包含在传递的一个且唯一的参数中,请参见下文)分解到第一个 token 中(命令字符串addremove)和其余参数(服务器名称)的数组。
  • 将参数分隔为命令和服务器名称数组,从而简化了其余代码。
  • 用来将RHS分成其第一个元素(分配给$var1, $var2 = <array>的标量)和其余元素(分配给$var1的数组)的$var2技术通常称为解构或拆包。它被记录在 Get-Help about_Assignment Operators 中,尽管没有给它起这样的名字。
  • -split $Edits使用-split运算符的方便的一元形式将用户输入分成由空格分隔的 token 数组,并将该数组传递给递归调用。
  • 请注意,EditServerList (-split $Edits)传递一个作为数组的参数-这就是为什么必须使用$Args[0]来访问它的原因。
  • 使用PowerShell的-split运算符(而不是.Split(' '))具有忽略开头和结尾空格以及忽略条目之间的多个空格的附加优点。
    通常,运算符-split优于[string]类型的.Split()方法-请参阅我的this answer
  • 不能在-notin中使用包含运算符Where-Object { $_ -notin $Servers }来接受数组作为RHS,以便从$Servers所包含的服务器列表中筛选出值。


  • 至于 ,您尝试了什么:
  • EditServerList ($Edits.split(' ') |Where {$_ -NotLike "add","remove"})(a)错误地尝试从参数数组中删除命令名称,即使递归调用需要它也是如此,但(b)实际上却没有这样做,因为-like的RHS不支持数组。 (顺便说一句:由于您正在查找确切的字符串,因此-eq本来是更好的选择。)
  • 由于您将参数作为第一个也是唯一的参数作为数组传递,因此$Inputs[0]实际上是指整个数组(命令名+服务器名),而不仅仅是它的第一个元素(命令名)。
  • 即使比较了整个数组,您也无需使用($Inputs[0] -eq "add"),因为-eq运算符(如果其LHS是数组)将执行数组过滤,并返回匹配元素的子数组。由于add是元素中的一个,因此返回了一个1元素子数组,该子数组在 bool(boolean) 上下文中是“真实的”。
  • 但是,您尝试用where {$_ -NotLike $Inputs[0]}清除命令名的尝试失败了,并且add没有删除-您实际上必须与$Inputs[0][0](原文如此)进行比较。
  • Where {$_ -NotLike ($Inputs |Where {$_ -Notlike $Inputs[0]})}不能将任何内容过滤掉,原因如下:
  • ($Inputs |Where {$_ -Notlike $Inputs[0]})始终返回一个空数组,因为-Notlike的RHS是一个数组,如上所述,该数组不起作用。
  • 因此,该命令与Where {$_ -NotLike @() }等效,该命令为LHS上的任何标量返回$True


  • 使用Splatting将数组作为单个参数传递

    参数展开(请参阅 Get-Help about_Splatting )也适用于数组:
    > function foo { $Args.Count } # function that outputs the argument count.

    > foo @(1, 2) # pass array
    1 # single parameter, containing array

    > $arr = @(1, 2); foo @arr # splatting: array elements are passed as indiv. args.
    2

    请注意如何需要一个中间变量,以及如何必须使用 @而不是 $作为中间变量的前缀才能执行飞溅。

    关于powershell - 将单个以空格分隔的字符串作为多个参数传递,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42227746/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com