Reputation: 304
I'm trying to write a switch statement that matches multiple integers in the same case. I have tried many different examples, have most recently landed on:
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
}
}
}
But this seems to get skipped and always ends up on the default bit after this, I cannot find a way to hit those two magic numbers and skip the rest of the code.
This switch statement is inside a Get-ChildItem
, I'm wondering if this would mean that $_
refers to the loop and not the switch? Running out of ideas, any advice would be appreciated. I think I'm running PowerShell 4 if that helps. Thanks
Upvotes: 1
Views: 3610
Reputation:
The problem is that $variable
is a regex match object, not an [int]
Try something like
[int]$variable.Value
Upvotes: 0
Reputation: 13547
Ok, I understand what you'd like to do.
So, as it turns out, the way Where-Object works is that you can put a filter block, just like in ForEach-Object, and if the filter emits and object, then matching objects continue down the pipeline.
With that being said, I think this would be much simpler as a Dir | Where | ForEach, rather than this much more complex mega-Where you've got going on.
In your example, you've got a regex looking for files which contain between 2 and 4 digits in them. If the file contains the numbers 291, or 292, you don't want to process them.
To replicate this, i've got a directory full of ISO files, called 290.iso, 291.iso, 292.iso and so on.
If this works, we should see a list of ISOs retured at the end of the Pipeline, minus the ones with the 'offending' digits, which we do not want.
Dir t:\ 2*.iso | Where {$_.BaseName -match $pattern} | ForEach-Object{
if ($_.BaseName -in (291,292)) {$null}
else{$_}
}
Results:
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
So, in your case, you'd just add one more ForEach to the end of the pipeline to process these macros or whatever you'd like to do.
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
}
Possibly a better approach would be to collect the files we DO want to work with in a variable, and then use ForEach on those.
#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
}
I know this doesn't answer your switch question, but I think this is a better approach to take. I'd hate to inherit the working Switch you come up with to accomplish this task.
This is kind of a strange usage of Where-Object, and if I may be totally honest, I'm not sure what this is attempting to accomplish. I've found that you'll always get better answers here if you'll explain what your code wants to do.
That being said, this works for me if I change your Where-Object into a ForEach-Object.
Functionally, your switch works. When I tested with this code structure:
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
}
}
}
Output:
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
So, I think the problem is that you're using the wrong cmdlet for this job. If I'm wrong and you have a good reason for using Where-Object, I'd love to learn it, so please let me know :)
Upvotes: 1
Reputation: 631
You have to convert the switch values to match into an array. This can be done using the @ character As an example, this code
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
writes this output
Nothing to see here
Case hit, moving on ...
Case hit, moving on ...
Upvotes: 0