PowerShell: Goodbye, Goto

When batch files were added to MS-DOS over 30 years ago, the BASIC programming language was the predominant programming language in use on microcomputers, and GOTO ruled to roost. Fortunately, things have improved. Here's how while, do while, do until, and for replace those classic commands in a variety of situations.

PowerShell: Goodbye, Goto

When batch files were added to MS-DOS over 30 years ago, the BASIC programming language was the predominant programming language in use on microcomputers. The BASIC language used the GOTO statement to provide the programmer the ability to repeat lines of code, so Microsoft added the Goto command to the batch file “language” to provide the same type of functionality. Listing 1 shows a simple batch file that illustrates the Goto command that jumps to batch label to repeat the Echo command 5 times.

@Echo Off

Set NUM=5

:REPEAT

Echo %NUM%

Set /A NUM-=1

If %NUM% GTR 0 Goto :REPEAT

Set NUM=

Listing 1: Batch file Goto example

 

When the batch file “language” was updated in Cmd.exe on the Windows NT platform, Microsoft enhanced the Call command to allow a label in a batch file to act as a simple subroutine, similar to the old BASIC GOSUB statement. Listing 2 shows an example of this use of the Call command.

@Echo Off

Call :SAYHELLO Ken

Echo End of batch file

Goto :END

:SAYHELLO

Echo Hello, %1

:END

Listing 2: Batch file with a subroutine

 

When you run the batch file in Listing 2, it outputs “Hello, Ken” and then “End of batch file.” The Call command causes execution to jump to the command after the label, and then execution returns to the line after the Call command. Also, batch file subroutines have no built-in way to return values without relying on environment variables and unintuitive Cmd.exe parsing quirks.

 

The point is that while the batch file Goto and Call commands both provide the ability to repeat lines of code, they do so in an unstructured manner. That is, a Goto or Call command can arbitrarily jump to any label in the batch file. As the batch file gets more complex, the use of Goto and/or Call eventually leads to what we call “spaghetti code” because the batch file’s logic gets harder and harder to follow.

 

PowerShell’s authors have bypassed the “spaghetti code” problem entirely. PowerShell has neither a Goto command nor a Call command, because it doesn’t need them. Instead, PowerShell has structured programming statements that replace both Goto (for iteration) and Call (for subroutines).

PowerShell Iteration

Iteration, or looping, refers to repeating code. PowerShell has four basic language statements that repeat lines of code based on a condition: while, do while, do until, and for. These four language statements, or looping constructs, effectively eliminate the need for the Goto command.

The While Statement

The while statement, or while loop, repeats lines of code as long as a particular condition is true. The script in Listing 3 shows an example script that sets a variable and outputs the value of that variable as long as it’s greater than 0. The output of the script is the numbers 5, 4, 3, 2, and 1.

$n = 5

while ( $n -gt 0 ) {

  $n

  $n--

}

Listing 3: The PowerShell while loop

 

The code in the parenthesis after the while keyword is the conditional statement that determines how many times the code in the curly braces (known as a scriptblock) runs. When you use a while loop, PowerShell evaluates the conditional statement at the beginning of the loop. Run the PowerShell command help about_While for more information about and examples of the while loop.

The Do Statement

The do statement, or do loop, is similar to the while statement except that PowerShell evaluates the conditional statement at the end of the loop rather than the beginning. The do loop requires either the while or the until keyword at the end of the scriptblock, so we usually refer to the do loop as a do while loop or a do until loop. Listing 4 illustrates the same loop as Figure 3 implemented as a do while loop.

$n = 5

do {

  $n

  $n--

} while ( $n -gt 0 )

Listing 4: The PowerShell do while loop

 

Listing 5 shows the same loop as Listing 3 and Listing 4, except that it’s implemented as a do until loop. The until keyword changes the loop logic to mean “repeat until the condition is true” instead of “repeat while the condition is true.”

$n = 5

do {

  $n

  $n--

} until ( $n -eq 0 )

Listing 5: The PowerShell do until loop

 

The only differences between the while, do while, and do until loops are where you test the conditional statement (beginning or end of the loop) and the repetition logic (while vs. until). Run the PowerShell command help about_Do for more information about and examples of the do while and do until loops.

The For Statement

The for statement, or for loop, repeats code in a scriptblock based on a set of conditions. The code in the for loop has an initialization statement, a condition statement, and a repetition statement. The initialization statement runs at the beginning of the loop and sets the initial conditions, the condition statement tests whether the loop should continue, and the repetition statement executes each time the loop runs. Listing 6 shows a simple example of a for loop.

for ( $n = 5; $n -ge 1; $n-- ) {

  $n

}

Listing 6: The PowerShell for loop

 

In Listing 6, the initialization statement is $n = 5, the condition statement is $n -ge 1, and the repetition statement is $n--. Listing 6 produces exactly the same output as Listings 3, 4, and 5. Run the PowerShell command help about_For for more information about and examples of the for loop.

Which Do I Use?

The four basic PowerShell iteration statements (while, do while, do until, and for) all allow you to repeat code based on a conditional statement. Use whichever of the four iteration statements make your code the clearest and easiest to read.

What about Foreach?

If you have more than a passing familiarity with PowerShell, you already know that PowerShell has a foreach statement, or foreach loop, that allows you to repeat commands for each item in an array or collection of objects. The foreach loop is more analogous to the batch file For command. Next time, I will discuss how you can replace the batch file For command in PowerShell. Stay tuned.

PowerShell Subroutines

PowerShell has no need for the Call command or subroutine labels. Instead, PowerShell has functions as in other structured programming languages. A function is simply a named block of code. To run the code in the function, just put the function’s name in your code. Listing 7 contains a simple PowerShell example of both defining and running a function.

function SayHello {

  "Hello, world"

}

# Run the function

SayHello

Listing 7: A simple PowerShell function

 

The function keyword tells PowerShell that we’re defining a function. When you put the function’s name in your code (as in last line of Listing 7), PowerShell runs the code in the function’s scriptblock (i.e., the code inside the curly braces).

 

Batch file subroutines allow you to pass parameters to the subroutine with the Call command, and you can use replaceable parameters in the subroutine (%1, etc., as seen Listing 2). The param statement at the top of a function allows you to do the same thing in PowerShell: It defines the function’s parameters. Listing 8 extends Listing 7 with a parameter.

function SayHello {

  param($name)

  "Hello, $name"

}

# Run the function

SayHello Ken

Listing 8: A PowerShell function with a parameter

 

When you run the code in Listing 8, PowerShell substitutes the $name variable in the function with the parameter passed from the last line (the string “Ken”).

 

Recall that batch file subroutines do not have a native way to return values. In contrast, PowerShell natively returns values from functions. In fact, the output of the function in Listing 8 is the output string itself. PowerShell also has no problem returning multiple values from a function; it will automatically return the values as a list (also called an array or a collection). Listing 9 shows a function that returns a list of three numbers.

function MyFunction {

  $list = @(1,2,3)

  $list

}

$result = MyFunction

# Output the list

$result

Listing 9: A PowerShell function that returns a list

Goto No More

PowerShell has no need for the Goto or Call commands. PowerShell’s loop constructs (while, do while, do until, and for) replace Goto, and functions replace Call. If you’re still writing batch files, this article will help you understand how to replace the Goto and Call commands in your new PowerShell scripts.

Hide comments

Comments

  • Allowed HTML tags: <em> <strong> <blockquote> <br> <p>

Plain text

  • No HTML tags allowed.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Lines and paragraphs break automatically.
Publish