Fun With PowerShell Logic Branching

Introduction

In this post, we’ll see how some of PowerShell’s logic branching works. Logic branching is where you execute certain lines of code only when a condition is true.

For all of the examples, we’ll display the code, then under it the result of our code. In this article I’ll be using PowerShell Core, 7.1.3, and VSCode. The examples should work in PowerShell 5.1 in the PowerShell IDE, although they’ve not been tested there.

To run a snippet of code highlight the lines you want to execute, then in VSCode press F8 or in the IDE F5. You can display the contents of an array variable (or any variable) by highlighting it and using F8/F5.

In either environment, you can run your entire script by pressing F5.

Logic Branching – if

No, I don’t mean “if” we want to do logic branching. if is a keyword in PowerShell. With it, you can pass in a condition, then execute code based on the value of the condition. This example will make it a bit more clear.

$var = 2
if ($var -eq 1)
{
  Clear-Host
  'If branch'
}
else
{
  Clear-Host
  'else branch'
}

Result:
else branch

Beside the if keyword are a set of parenthesis ( ). In it, you create some kind of expression, but, and this is important, the result of the equation must be either True or False.

In this example, I created a variable $var and set the value to 2. Then, inside the parenthesis I used $var - eq 1.

Following this I have a set of squiggly braces { } with code inside it. In PowerShell, this is known as a script block.

If my condition is true, it will execute the first script block. But what if you want to do something if it evaluates to false? That’s where the next keyword comes in, else.

Immediately after the script block associated with the if, you add the else keyword, followed by a second script block to be executed.

In the example above, the condition will evaluate to false, so the code in the else script block will run, displaying the result of “else branch“.

PowerShell also supports another keyword, elseif. I almost hesitate to provide a demo, because most developers say if you need to fall into an elseif, you should then change your code to use another branching method, which we’ll cover next. However for completeness let’s see an example.

$var = 2
if ($var -eq 1)
{
  Clear-Host
  'If branch'
}
elseif ($var -eq 33)
{
  Clear-Host
  'elseif branch'
}
else
{
  Clear-Host
  'else branch'
}

Result:
else branch

As before, we start with an if ($var -eq 1), but following that is our elseif. It will then check the condition in the elseif, ($var -eq 33). If it doesn’t find a match for it, it flows to the next section, the else.

Obviously if it finds a match, it executes the script block associated with the elseif. Once done it skips over any following elseif or else statements and goes on to the following our entire if construct.

A few things, first you can have elseif statements without an else. However it’s generally a good idea to have a default code handler should you not execute any of the other if / elseif statements.

Second, you can have as many elseif statements as you want. But as the old saying goes, just because you can do something, doesn’t mean you should. Most PowerShell developers (myself included) say if you have to resort to an elseif, you should really be using a switch.

Speaking of the switch….

More Fun with Logic Branching – switch

In addition to the if statement, there is another way to branch your code, the switch statement.

$var = 42
switch  ($var)
{
  41 {'Forty One'}
  42 {'Forty Two'}
  43 {'Forty Three'}
  default {'default'}
}

Result:
Forty Two

With the switch statement, you pass in a value. Unlike the if, the value does not need to evaluate to True or False, it can be any value.

It will then execute the script block that follows, evaluating each value in the list. If it finds a match, it will execute the code in the script block that follows.

In the example above, it finds a match on 42, and runs the code in the script block which prints out the text ‘Forty Two‘.

One issue you may encounter is multiple matches.

$var = 42
switch  ($var)
{
  41   {'Forty One'}
  42   {'Forty Two'}
  '42' {'Forty Two'}
  43   {'Forty Three'}
  default {'default"}
}

Result:
Forty Two
Forty Two

Here, it went down the list and found the first match of integer 42. It executed the script block, and continued down the list.

It next found the string of '42'. It converted the string to the same datatype as what was passed in, an integer 42, found a match, and executed that script block.

So how to stop execution after the first match? That’s where break comes in. When PowerShell finds break it will stop code execution and exit to the next line after the switch.

$var = 42
switch  ($var)
{
  41   {'Forty One'; break}
  42   {'Forty Two'; break}
  '42' {'Forty Two'; break}
  43   {'Forty Three'; break}
  default {'default'; break}
}

'Exit to this point'

Result:
Forty Two
Exit to this point

As you can see from the results, the switch found the first match at the int 42. The break statement said “skip the rest and go to the next line after”, which prints out Exit to this point.

This brings up the subject of type coercion. This is the converting of one data type before comparing to another. In PowerShell, anytime it compares values of two different datatypes, it converts the datatype on the right to match the datatype on the left.

For example, if you had an equation if ( 33 -eq '33') it will convert the string '33', on the right side of the -eq, to the datatype on the left side of the -eq, an integer 42.

With the switch statement, the left value is the one being passed in, in this case the variable $var. The right side are the values switch is looking at, here 41, 42, 43. This is something to keep in mind whenever you are writing your code.

In this example, it won’t make a difference.

$var = '42'
switch  ($var)
{
  41 {'Forty One'}
  42 {'Forty Two'}
  43 {'Forty Three'}
  default {'default'}
}

Result:
Forty Two

The code went down the list, converting each value to a string. It took the int, 42 and converted it to a string. It then found a match with the original string of 42 in the $var variable and printed out the ‘Forty Two‘ as found in the script block.

Let’s take a slightly different example.

$var = '042'
switch  ($var)
{
  41 {'Forty One'}
  42 {'Forty Two'}
  43 {'Forty Three'}
  default {'default'}
}

Result:
default

In this case it compared each value, but the string 042 doesn’t match the converted int of '42' so it didn’t match.

So what’s with the output of default? If the switch statement doesn’t find a match, it will execute in the script block associated with default.

The default is optional, if you omit it and no match is found and the switch simply exits and continues to the next line after the switch.

As a final point, I want to mention you don’t have to contain everything in the switch’s script blocks to a single line. This is perfectly valid code.

$var = 42
switch  ($var)
{
  41   {
         'Forty One'
         break
       }
  42   {
         'Forty Two'
         break
       }
  '42' {
         'Forty Two'
         break
       }
  43   {
         'Forty Three'
         break
       }
  default {
            'default'
            break
          }
}

While this example is a bit harder to read, you will encounter situations where trying to condense your script block to a single line will be difficult so don’t hesitate to use multiple lines if it improves readability.

Conslusion

This post focused on the logic branching mechanisms built into PowerShell, if and switch. Hopefully this will give you a better understanding of your options for handling conditional code execution in PowerShell.

The demos in this course came from my Pluralsight course PowerShell 7 Quick Start for Developers on Linux, macOS and Windows, one of many PowerShell courses I have on Pluralsight. All of my courses are linked on my About Me page.

If you don’t have a Pluralsight subscription, just go to my list of courses on Pluralsight. At the top is a Try For Free button you can use to get a free 10 day subscription to Pluralsight, with which you can watch my courses, or any other course on the site.

Advertisement

2 thoughts on “Fun With PowerShell Logic Branching

  1. If “most developers say if you need to fall into an elseif, you should then change your code to use another branching method,” then most developers have never worked with complicated code. if-elseif will allow you to prioritize unrelated (or loosely related) conditions where switch will not. For example:
    if (emergencyAlert -ne 0) { throwRedFlagException(); }
    elseif (notificationCount -gt 0) { showNotifications(); }
    else { displayMessage(‘Nothing to report’); }
    It prioritizes the emergencyAlert condition. Only when that condition fails will it process the rest of the conditions in the if-elseif-else block. You can’t do that with a single switch block.
    And a suggestion: get someone to proofread your posts. Grammar and spelling errors provide a jarring experience and distract from your message.

    1. For a complex situation as you describe, I would completely agree the if/elseif is the better fit.

      Let’s take a different example though, where you have a script that reads data from a CSV file and inserts it into a database. There could be a set of business rules that need to be applied that the switch is the better fit for. Perhaps our CSV file has a column for the state name, and the database only wants the abbreviated form of the state. Here a switch makes far more sense.

      As developers we have to use our own judgement and pick the right construct for a particular situation. General rules are just that, general, and should absolutely be broken if it makes sense as it did in your example.

      As to your suggestion to get a proofreader, are you volunteering?

      I provide these posts for free to the community and receive no direct compensation for them. As such, paying an editor does not make good financial sense for me. I’ve had people volunteer in the past, but after a few posts they fade away.

      Additionally, I use a conversational tone for these posts as if the reader and I were sitting down having a one-on-one discussion. The overwhelming majority of people aren’t going to notice a few grammatical slips here and there, instead focusing on the overall content. These are free blog posts, not a book that you’ve paid money for. I am sorry if they bother you, but you’ll have to decide if the content is worth putting up with them or if you’ll look elsewhere. Either way I appreciate the feedback.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s