Powershell - 如何声明一个数组以用于+ =运算符

时间:2014-03-26 19:43:27

标签: arrays powershell foreach powershell-v3.0

我可以直观地找出大多数语言,但显然不是Powershell。

我想创建一个数组数组(这将包含磁盘目录和计数,所以稍后我可以验证我们至少有那么多文件)。

从那个数组数组中,我想拉出一个只有目录名的数组,这样我就可以将它传递给Get-ChildItem。

$DirInfo = @('d:\Work',2),
            ('d:\Temp',3) 

$DirNameArray=@()                     #declare empty array 
foreach ($item in $DirInfo) 
  {
    $DirNameArray += , $item[0]       #tried with and without the comma here 
    Write-Host 'Loop1 '  $item[0] 
  }

write-host $DirNameArray.count

#Let's Verify what we got so we know how many items we have in our array 
Write-Host "Verify with a loop"
foreach ($dir in $DirNameArray) 
  {
    Write-Host 'Loop2:'  $dir
  }

Write-Host "Verify the other way"
Write-Host $DirNameArray

实际结果:

Loop1  d:\Work
Loop1  d:\Temp
1 
Verify with a loop
Loop2: d:\Workd:\Temp
Verify the other way
d:\Workd:\Temp

我不明白为什么Loop2没有执行两次。 看起来= +只是将值串起来而不是向我的数组中添加一个名为$ DirNameArray的新项。

我仍然感到困惑,我创建的一个文件就是这样,并给了我预期的结果:

$a = "one","two"
Write-Host $a.count 

$a += "three" 
Write-Host $a.count 

结果:

2
3

如果上述工作有效,为什么我的代码不起作用?

我创建的第二个文件是这样的 - 我不理解结果。我甚至将变量名称设置为不同,因此我不会处理该变量的任何先前定义或值:

$DirNameArray5="abc","def"
write-host $DirNameArray5.count

$DirNameArray5 += "xyz"
write-host $DirNameArray5.count
$DirNameArray5 += @("opq")
write-host $DirNameArray5.count

结果:

1
1
1

$DirNameArray7="abc","def"
write-host $DirNameArray7.count

$DirNameArray7 += "xyz"
write-host $DirNameArray7.count
$DirNameArray7 += @("opq")
write-host $DirNameArray7.count

结果:

2
3
4

显然,如果你曾经将变量定义为字符串,那么很难让Powershell将其重新定义为数组。

但我还有原来的问题。如何定义一个空数组,以便我可以使用+ =运算符在循环中添加它。

$DirNameArray=@()

我最后使用.GetType()方法来查看我的变量实际上是什么:     PS C:\ Users \ nwalters> $ DirNameArray5.GetType()

IsPublic IsSerial Name                                     BaseType                                                                                   
-------- -------- ----                                     --------                                                                                   
True     True     String                                   System.Object                                                                              



PS C:\Users\nwalters> $DirNameArray7.GetType()

IsPublic IsSerial Name                                     BaseType                                                                                   
-------- -------- ----                                     --------                                                                                   
True     True     Object[]                                 System.Array      

底线 - 这就是我想要的 - 尽可能少的代码行没有循环:

[string]$x=@()    # declare empty array 
Write-Host $x.GetType() 
$x += "one" 
$x += "two" 
Write-Host $x.count 
Write-Host $x 

实际结果

System.String
1
onetwo

期望的结果:

object[]  or string[]??? 
2
one two 

2 个答案:

答案 0 :(得分:2)

Powershell不允许您创建一个空数组,也不能让您将数组清空为零(一个例外)。我发现有两种方法可以解决此问题:

方法1:使用-OutVariable来命名变量,以使用您的输入创建一个数组

Example: gci C:\TestDir1 -OutVariable test  

使用.GetType()方法返回:


$test.GetType()


    Directory: C:\TestDir1


Mode                LastWriteTime         Length Name                                             
----                -------------         ------ ----                                             
-a----        4/20/2020  11:36 AM           8015 Test1.xls                                        
-a----        6/26/2020  12:59 PM              0 test2.txt                                        

Module                     : CommonLanguageRuntimeLibrary
Assembly                   : mscorlib, Version=4.0.0.0, Culture=neutral, 
                             PublicKeyToken=b77a5c561934e089
TypeHandle                 : System.RuntimeTypeHandle
DeclaringMethod            : 
BaseType                   : System.Object
UnderlyingSystemType       : System.Collections.ArrayList
FullName                   : System.Collections.ArrayList

这将创建一个名为$ test的新变量,它是一个数组(因为其中包含多个项目)。 $test.gettype()将对象显示为数组。

方法2:明确声明一个包含两个虚拟对象的数组,然后删除这两个虚拟对象。

[System.Collections.ArrayList]$array = "value1", "value2"
$array.remove("value1")
$array.remove("value2")

使用gettype方法仍将显示$test是一个数组,即使它为空:

> $test.GetType()

IsPublic IsSerial Name                                     BaseType                               
-------- -------- ----                                     --------                               
True     True     ArrayList                                System.Object 

该数组现在将完全为空,可用于存储任何新输入。除非您像我在示例中那样明确命名变量类型,否则这是行不通的(不确定原因)。示例如下所示:

$test = "value1", "value2"

$test.Remove("value1")

Exception calling "Remove" with "1" argument(s): "Collection was of a fixed size."
At line:3 char:1
+ $test.Remove("value1")
+ ~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : NotSupportedException

P.S。我知道这是一个旧主题,但没有得到答案,我自己才遇到此问题,因此我为其他搜索此问题的人回答。

答案 1 :(得分:1)

以下代码在两台不同的计算机上进行测试,均使用PowerShell 2.0。你可以尝试这个并发布结果。

# declare an empty array
$var = @()
write-host "var.count = '$($var.count)'  var.type ='$($var.GetType())'  var.type.BaseType = '$($var.GetType().BaseType)'"

# add a single item
$var += "single item"
write-host "var.count = '$($var.count)'  var.type ='$($var.GetType())'  var.type.BaseType = '$($var.GetType().BaseType)'"

# add an array
$var += , @("array 1 - item 1","array 1 - item 2")
write-host "var.count = '$($var.count)'  var.type ='$($var.GetType())'  var.type.BaseType = '$($var.GetType().BaseType)'"

# display the 'single item'
write-host "single item = '$($var[0])'"

# display first element of array item
write-host "first element of array item = '$($var[1][0])'"

给了我

var.count = '0'  var.type ='System.Object[]'  var.type.BaseType = 'array'
var.count = '1'  var.type ='System.Object[]'  var.type.BaseType = 'array'
var.count = '2'  var.type ='System.Object[]'  var.type.BaseType = 'array'
single item = 'single item'
first element of array item = 'array 1 - item 1'