Thursday, December 3, 2015

Powershell Switch for a numeric range

There are several ways of handling a range of values in a Switch statement in powershell. In this example, I will show a simple conversion of a numeric month value to a quarter [string].

First example:
switch($month){
 {1..3 -contains $_}{"Q1"}
 {4..6 -contains $_}{"Q2"}
 {7..9 -contains $_}{"Q3"}
 {10..12 -contains $_}{"Q4"}
 
}


The range operator returns an array of the numbers in that specified range, so we use -contains to test our value. If we left out -contains, all switch values would match as no comparison is being made, yet the range is being evaluated as true.

Second example:
switch($month) {
 {$_ -le 3} {"Q1";break;}
 {$_ -le 6} {"Q2";break;}
 {$_ -le 9} {"Q3";break;}
 {$_ -le 12} {"Q4"; break;}
}


The key to this example is the Break statement. Without this, everything would match as the switch operator continues to evaluate for all possible matches (not just the first one). Break will cause it to stop evaluating.

Third example:

switch($month) {
 {$_ -ge 1 -and $_ -le 3} {"Q1"}
 {$_ -ge 4 -and $_ -le 6} {"Q2"}
 {$_ -ge 7 -and $_ -le 9} {"Q3"}
 {$_ -ge 10 -and $_ -le 12} {"Q4"}

}


The more "wordy" example with multiple conditions and the -And. This may be more readable, however the first example does a pretty good job with this. The functionality is far more obvious than example #2. In any case, using conditions to check a range of values will save time and code. Alternatively (though not very elegant or practical), you can use a regex switch for this:

switch -regex ([string]$month) {
 "^[1-3]$" {"Q1"}
 "^[4-6]$" {"Q2"}
 "^[7-9]$" {"Q3"}
 "^1[0-2]$" {"Q4"}
}

3 comments:

  1. thank for this! the syntax for ranges within the switch statement wasn't inherently intuitive. this saved me from destroying some stuff.

    ReplyDelete
  2. For your Regex example, "^[10-12]$" {"Q4"} should look like "^1[0-2]$". The way it is now, it will match a single character - either the literal character "1", a character in the range between "0" and "1", or the literal character "2".

    ReplyDelete