tsunami

log in
history

PowerShell: flow control

Luke Breuer
2008-12-20 09:55 UTC

Flow Control
  • braces are mandatory
    • this isn't always necessary, but certain ambiguities caused more errors than brace-lessness was worth
  • conditions can be pipelines, e.g. dir | ? {$_.length -gt 1mb}
if
if ($life -eq 42)
{
    "Paradise!"
}
elseif ($life -gt 42)
{
    "Too far!"
}
else
{
    "Keep going!"
}
When using interactive mode, one must include elseif or else on the same line as the }, as otherwise the interpreter will assume the statement has been completed.
while
$progress = 22
while ($progress -lt 42)
{
    "$(42 - $progress) step$(if ($progress -eq 41){''}else{'s'}) away from paradise"
    $progress++
}
do
$i = 2
do
{
    "$i instances of foolishness"
}
while ($i++ -lt 10)
for
for ($i = 0; $i -lt 7; $i++)
{
    $i
}
foreach
  • syntax: foreach (<variable> in <pipeline>) { <statementList }
  • no type may be specified for the loop variable
  • the loop variable does not go out of scope; it is set to the last element processed when the loop exits
  • the <pipeline> is evaluated fully before loop iteration starts
  • $foreach, the enumerator, is available inside foreach loops; it can be useful to be able to call $foreach.MoveNext to skip elements
  • most everything that implements IEnumerable can be iterated over with a foreach loop, except for strings and Hashtables
  • if <pipeline> returns a scalar object, it is treated as a single-element array, even if the scalar value is $null
$length = 0
foreach ($f in dir *.txt)
{
    $length += $f.length
}
"$($length / 1mb) MB of text files in here"
switch
  • -wildcard, -regex, and -match can be used immediately after the switch keyword; -case can also be specified, either alone or with one of the above three
    • -match populates $matches
  • if the <pipeline> being switched returns a collection, the switch statement will loop
  • -file results in only one line being read at a time
  • the $switch variable is available for altering flow control, like $foreach

switch (2)
{
  1 { 'one' }
  2 { 'two' }
  2 { 'two again' }
  default { 'something else' }
}

switch -regex ('earth', 'air', 'fire', 'water')
{
  ir { 'contains "ir"' }
  { $_.length -eq 3 } { "length is 3" }
  default { "default" }
}

switch -wildcard -file log.txt
{
  *warning* { 'warning!' }
  *error* { 'error!' }
}
break and continue
Loop keywords may be prefixed with a label in the form :label_name. This is useful both for use of the evil goto as well as using break label_name to break out of multiple loops at once. continue may also be used this way. In fact, the label to break out of or continue to is actually an expression, meaning it could be a variable or whatnot. Control of flow can cross script and function call boundaries.