首页 > 解决方案 > 在 switch 语句中分配变量

问题描述

大家早上好!

自从我在另一篇文章中发现它以来,我一直在搞乱 switch 语句。

我在下面的代码中遇到了这个问题,它使用相同的信息打印多行,我明白它为什么这样做,但是我不知道如何解决它。我相信当我分配变量时它会搞砸,但我不太确定。有人可以指出我可能导致问题的正确方向吗?任何帮助表示赞赏。

$gc = Get-ChildItem -Path 'C:\users\abrah\OneDrive\Desktop'  
Foreach ($File in $gc) {
 
    switch -Wildcard ($file) {

        "deskt*" { $Desk = "This is the location: $($File.FullName)" }
        "*v*" { $VA = "This is the location: $($File.FullName)" }

    }

    $VCount = $va | Measure-Object | Select-Object -ExpandProperty Count
    $Dcount = $Desk | Measure-Object | Select-Object -ExpandProperty Count

    $PS = [pscustomobject]@{
        DesktopLocation = $Desk
        DCount          = $Dcount
        VLocation       = $VA
        VCount          = $VCount
 
    }

    $PS
}

关于脚本:我只是想在我的桌面上找到任何以 开头的文件deskt,以及其中包含字母V的任何文件。然后我将它扔到一个自定义对象中,同时尝试计算有多少文件包含这些关键字母。

这是结果顺便说一句:

在此处输入图像描述

标签: powershell

解决方案


至于您switch的基于 -statement 的方法:

  • switch本身能够处理集合,因此无需将其包装在foreach循环中。

  • 您正在寻找的是从输入中建立两个集合,这需要您:

    • 初始化$Desk$VA作为集合数据类型。
    • switch在分支处理程序中附加到这些集合。
# Initialize the collections.
$Desk = [System.Collections.Generic.List[string]] @()
$VA = [System.Collections.Generic.List[string]] @()

# Make `switch` loop over the .FullName values of all items in the target dir.
switch -Wildcard ((Get-ChildItem C:\users\abrah\OneDrive\Desktop).FullName) {
  '*\deskt*' { $Desk.Add("This is the location: $_") } # add to collection
  '*\*v*'    { $VA.Add("This is the location: $_") }   # add to collection
}

# Construct and output the summary object
[pscustomobject] @{
  DesktopLocation = $Desk
  DCount          = $Desk.Count
  VLocation       = $VA
  VCount          = $VA.Count
}

笔记:

  • 虽然可以使用数组作为集合类型,但使用 向数组“追加”+=虽然方便,但效率低下,因为每次都必须在后台创建一个数组,因为数组在元素计数方面是不可变的.
    虽然对于只有几个元素的数组可能无关紧要,但将其System.Collections.Generic.List`1用作有效可扩展的集合类型是一个好习惯。

  • 也就是说,考虑到诸如switch和循环之类的语句在分配给变量时foreach可以充当表达式,如果要在单个集合中捕获所有输出,您甚至不需要显式的集合类型,这既简洁又高效;例如:
    $collection = foreach ($i in 0..2) { $i + 1 }将数组存储1, 2, 3$collection;请注意,如果只输出一个对象,$collection不会是数组,因此要确保可以使用[array] $collection = ...


或者,一个更简单的解决方案是利用通过-Filter参数进行基于通配符的过滤速度很快的事实,因此即使调用两次也不会成为问题:Get-ChildItem

$dir = 'C:\users\abrah\OneDrive\Desktop' 
[array] $Desk = (Get-ChildItem -LiteralPath $dir -Filter deskt*).FullName
[array] $VA = (Get-ChildItem -LiteralPath $dir -Filter *v*).FullName

[pscustomobject] @{
  DesktopLocation = $Desk
  DCount          = $Desk.Count
  VLocation       = $VA
  VCount          = $VA.Count
}

推荐阅读