我需要将数组列表从脚本n.1传递到脚本n.2,并用while周期对其进行修改
[System.Collections.Arraylist]$ArrBkp=@()
$ArrObj = New-Object psobject -Property @{Type="Full";Id=1001}
[void]$ArrBkp.Add($ArrObj)
$ArrObj = New-Object psobject -Property @{Type="Diff";Id=1002}
[void]$ArrBkp.Add($ArrObj)
$ArrObj = New-Object psobject -Property @{Type="Full";Id=1003}
[void]$ArrBkp.Add($ArrObj)
$ArrObj = New-Object psobject -Property @{Type="Diff";Id=1004}
[void]$ArrBkp.Add($ArrObj)
$ArrObj = New-Object psobject -Property @{Type="Diff";Id=1005}
[void]$ArrBkp.Add($ArrObj)
$ArrBkp
[CmdletBinding()]Param(
[Parameter(ValueFromPipeline=$true)]
$ArrBkp,
[Parameter()]
$Id
)
$ArrBkp.Reverse()
foreach ($Bkp in $ArrBkp) {
while ($Bkp.Id -gt $Id) {$Bkp;$ArrBkp.Remove($Bkp)}
}
$ArrBkp
我期望的是:
PS C:\Users\dio\Documents\script\PS-Rest> .\PS-GetBak.ps1 | .\PS-Rest.ps1 -Id 1004
Id Type
-- ----
1004 Diff
1003 Full
1002 Diff
1001 Full
说明:while循环应从ID值为gt 1004的arraylist中删除对象
实际结果: 只有arraylist中的最后一个值通过管道传递到脚本n.2,导致while循环错误
In C:\Users\dio\Documents\script\PS-Rest\PS-Rest.ps1:11 car:49
+ while ($Bkp.Id -gt $Id) {$Bkp;$ArrBkp.Remove <<<< ($Bkp)}
+ CategoryInfo : InvalidOperation: (Remove:String) [], RuntimeException
+ FullyQualifiedErrorId : MethodNotFound
答案 0 :(得分:1)
退后一步:
PowerShell按需创建([object[]]
)阵列,“修改”阵列通常意味着简单地自动创建带有修改的原始阵列的副本已应用。
除非性能和内存保留至关重要,否则通常没有理由在PowerShell中使用[System.Collections.ArrayList]
之类的类型。
这包括数组的初始构造,假设:
从脚本中输出多个对象通过管道将它们逐个发送,并在分配给变量时隐式地将它们收集在数组中。 >
PowerShell的,
运算符用于显式构造数组非常灵活。
因此,您的PS-GetBak.ps1
脚本可以简化如下:
# Construct multiple custom objects and send them all to the pipeline.
[pscustomobject] @{Type="Full";Id=1001}
[pscustomobject] @{Type="Diff";Id=1002}
[pscustomobject] @{Type="Full";Id=1003}
[pscustomobject] @{Type="Diff";Id=1004}
[pscustomobject] @{Type="Diff";Id=1005}
现在,您可以让PS-Rest.ps1
对输入执行过滤操作,并简单地忽略不想要的输入,而将其他输入传递给:
[CmdletBinding()]
Param(
[Parameter(ValueFromPipeline = $true)]
$Bkp
,
$Id
)
process {
if ($Bkp.Id -le $Id) {
$_ # pass through
}
}
请注意使用process
块,它是一次处理所有管道输入所必需的。
但是,这不能解决结果数组(列表)的所需反转 ,但是您可以在事实发生之后进行 :
# Chain the two scripts in a pipeline and collect the result.
$resultArray = @(PS-GetBak.ps1 | PS-Rest.ps1 -Id 1004)
[array]::Reverse($resultArray) # reverse the array in place.
请注意管道周围的@(...)
,可确保输出始终为 数组,因为PowerShell会按原样报告单个输出对象,而不是一个单元素数组。
如果您确实想将阵列的反转集成到PS-Rest.ps1
中,则需要使用System.Collections.Stack
实例进行更多工作:
[CmdletBinding()]
Param(
[Parameter(ValueFromPipeline = $true)]
$Bkp
,
$Id
)
begin {
# Create a stack as an aux. data structure for output in reverse order.
$stack = [Collections.Stack]::new()
}
process {
if ($Bkp.Id -le $Id) {
$stack.Push($_) # add to stack
}
}
end {
# Output the stack, which enumerates the elements in reverse order.
$stack
}
然后将呼叫简化为:
$reversedResultArray = @(PS-GetBak.ps1 | PS-Rest.ps1 -Id 1004)
答案 1 :(得分:0)
好吧,我对其进行了重新设计,因此与原始版本非常接近。除了我要通过属性名称传递管道。我有点在子属性下走私arraylist。由于某种原因,PS脚本无法返回顶级数组列表。而且管道无论如何一次只能处理一个元素。并收集要删除的元素,然后在第二个循环中删除。这样,它不会中断第一个循环。另外,使用while语句也没有意义,因为删除后条件永远不会改变。
ps-getbk.ps1:
[System.Collections.Arraylist]$ArrBkp=@()
$ArrObj = New-Object psobject -Property @{Type="Full";Id=1001}
[void]$ArrBkp.Add($ArrObj)
$ArrObj = New-Object psobject -Property @{Type="Diff";Id=1002}
[void]$ArrBkp.Add($ArrObj)
$ArrObj = New-Object psobject -Property @{Type="Full";Id=1003}
[void]$ArrBkp.Add($ArrObj)
$ArrObj = New-Object psobject -Property @{Type="Diff";Id=1004}
[void]$ArrBkp.Add($ArrObj)
$ArrObj = New-Object psobject -Property @{Type="Diff";Id=1005}
[void]$ArrBkp.Add($ArrObj)
[pscustomobject]@{ArrBkp=$ArrBkp}
ps-rest.ps1:
[CmdletBinding()]Param(
[Parameter(ValueFromPipelineByPropertyName=$true)]
$ArrBkp,
[Parameter()]$Id
)
$ArrBkp.Reverse()
$dellist = foreach ($Bkp in $ArrBkp) {
if ($Bkp.Id -gt $Id) {$Bkp}
}
foreach ($Bkp in $dellist) {
$ArrBkp.remove($Bkp)
}
$ArrBkp
.\PS-GetBak.ps1 | .\PS-Rest.ps1 -Id 1004
的输出
Id Type
-- ----
1004 Diff
1003 Full
1002 Diff
1001 Full