循环内的多个开关值

时间:2015-12-01 16:49:45

标签: powershell switch-statement powershell-v4.0

我正在尝试编写一个在同一情况下匹配多个整数的switch语句。我尝试了很多不同的例子,最近才登陆:

Get-ChildItem $folder -Filter "*.$($extension)" | Where-Object {

    $name = $_.Name
    $pattern = '(\d{2,4})'
    $metric = ([regex]$pattern).Matches($name)
    $variable = $metric.Item(0)

    switch ($variable) {
        {291,292 -contains $_} {
            Write-Host "Skip these numbers...`n"
            break
        }
        default {
            #process other numbers
        }
    }
}

但是这似乎被跳过并且在此之后总是在默认位上结束,我找不到一种方法来击中这两个幻数并跳过剩下的代码。

这个switch语句在Get-ChildItem里面,我想知道这是否意味着$_是指循环而不是交换机?没有想法,任何建议将不胜感激。我认为如果有帮助我正在运行PowerShell 4。感谢

3 个答案:

答案 0 :(得分:1)

好的,我明白你想做什么。

因此,事实证明,Where-Object的工作方式是你可以放置一个过滤器块,就像在ForEach-Object中一样,如果过滤器发出并反对,那么匹配的对象继续沿着管道行进。

话虽如此,我认为这将是很多更简单的Dir |哪里| ForEach,而不是这个更复杂的巨型 - 你在哪里继续前进。

在您的示例中,您有一个正则表达式,用于查找包含2到4位数字的文件。如果文件包含数字291或292,则不想处理它们。

为了复制这个,我有一个充满ISO文件的目录,名为290.iso,291.iso,292.iso等等。

如果这样做,我们应该看到在管道末端重复的ISO列表,减去那些我们不想要的“有问题”数字的列表。

Dir t:\ 2*.iso | Where {$_.BaseName -match $pattern} | ForEach-Object{
    if ($_.BaseName -in (291,292)) {$null}
    else{$_}
    } 

结果:

Mode                LastWriteTime         Length Name                                                                                                 
----                -------------         ------ ----                                                                                                 
-a----        12/1/2015  12:40 PM             12 290.iso                                                                                              
-a----        12/1/2015  12:40 PM             12 293.iso                                                                                              
-a----        12/1/2015  12:40 PM             12 294.iso                                                                                              
-a----        12/1/2015  12:40 PM             12 295.iso 

因此,在您的情况下,您只需在管道末尾再添加一个ForEach来处理这些宏或您想要做的任何事情。

Get-ChildItem $folder -Filter "*.$($extension)" | 
    Where-Object {$_.BaseName -match $pattern} |
         ForEach {
            #Dump the files is their name contains any of these numbers
            if ($_.BaseName -in (291,292)) {$null}
            else{$_}
            } | ForEach-Object {
                #Run your macros here
                }

可能更好的方法是收集我们想要在变量中使用的文件,然后在那些上使用ForEach。

#Only return files with numbers in the name
$MatchingFiles = Get-ChildItem $folder -Filter "*.$($extension)" | 
    Where-Object {$_.BaseName -match $pattern} 

#Remove files with 291, 292 in their name   
$FilteredFiles = $MatchingFiles | 
         ForEach {
            #Dump the files is their name contains any of these numbers
            if ($_.BaseName -in (291,292)) {$null}
            else{$_}
            } 

#Run the macros for each file remaining            
ForEach ($file in $FilteredFiles){
    #Run your macros here
    }

我知道这不能回答你的转换问题,但我认为这是一个更好的方法。我不想继承你提出的工作Switch来完成这项任务。

OLD

这是Where-Object的一种奇怪用法,如果我可能完全诚实,我不确定这是在尝试实现什么。我发现如果你能解释你的代码想要做什么,你总会得到更好的答案。

话虽如此,如果我将Where-Object更改为ForEach-Object,这对我有用。

从功能上讲,您的开关可以正常工作。当我使用此代码结构进行测试时:

forEach ($variable in (290..295)){
switch ($variable) {
        {291,292 -contains $_} {
            Write-Host "Skip these numbers... $variable"
            break
        }
        default {
            "We won't skip this one $variable"#process other numbers
        }
    }

    }

输出:

We won't skip this one 290
Skip these numbers.... 291
Skip these numbers.... 292
We won't skip this one 293
We won't skip this one 294
We won't skip this one 295

所以,我认为问题在于你使用了错误的cmdlet来完成这项工作。如果我错了,你有充分的理由使用Where-Object,我很乐意学习它,所以请让我知道:)。

答案 1 :(得分:0)

您必须将开关值转换为匹配到数组中。这可以使用 @ 字符完成。例如,此代码

function checkSwitch($switchValue) {
    switch ($switchValue) {
        { @(291, 292) -contains $_ } {
            Write-Host "Case hit, moving on ..."
        }

        default {
            Write-Host "Nothing to see here"
        }
    }
}

checkSwitch 42
checkSwitch 291
checkSwitch 292

写出此输出

Nothing to see here
Case hit, moving on ...
Case hit, moving on ...

答案 2 :(得分:0)

问题是$variable是正则表达式匹配对象,而不是[int]

尝试类似

的内容
[int]$variable.Value