In this about page, there is a code block (below) that shows off the $ForEach
automatic variable, but it also has syntax like a subroutine in batch. I cannot find documentation on how this piece of code functions or what the language construct is called. I believe it's a PowerShell v5 addition, but reading the release notes didn't help me either. What does :tokenLoop foreach ($token in $tokens)
represent?
function Get-FunctionPosition {
[CmdletBinding()]
[OutputType('FunctionPosition')]
param(
[Parameter(Position = 0, Mandatory, ValueFromPipeline, ValueFromPipelineByPropertyName)]
[ValidateNotNullOrEmpty()]
[Alias('PSPath')]
[System.String[]]
$Path
)
process {
try {
$filesToProcess = if ($_ -is [System.IO.FileSystemInfo]) {
$_
}
else {
Get-Item -Path $Path
}
foreach ($item in $filesToProcess) {
if ($item.PSIsContainer -or $item.Extension -notin @('.ps1', '.psm1')) {
continue
}
$tokens = $errors = $null
$ast = [System.Management.Automation.Language.Parser]::ParseFile($item.FullName, ([REF]$tokens), ([REF]$errors))
if ($errors) {
Write-Warning "File '$($item.FullName)' has $($errors.Count) parser errors."
}
:tokenLoop foreach ($token in $tokens) {
if ($token.Kind -ne 'Function') {
continue
}
$position = $token.Extent.StartLineNumber
do {
if (-not $foreach.MoveNext()) {
break tokenLoop
}
$token = $foreach.Current
} until ($token.Kind -in @('Generic', 'Identifier'))
$functionPosition = [pscustomobject]@{
Name = $token.Text
LineNumber = $position
Path = $item.FullName
}
Add-Member -InputObject $functionPosition -TypeName FunctionPosition -PassThru
}
}
}
catch {
throw
}
}
}
In PowerShell
version 3.0 and up(at least since version 2.0), the following statement types are optionally labelled:switch
foreach
for
while
do
Now, what does this mean? It means that you can supply a label name as an argument to
break
orcontinue
statement inside the body of your labeled statement and have the flow control apply to the statement indicated by the label.Consider this example:
You might expect the "Let's process [...]" string to appear only twice, since we
continue
in the case ofBob
, but since the immediate parent statement is aswitch
, it didn't actually apply to theforeach
statement.Now, if we can explicitly state that we want to continue the
foreach
loop rather than the switch statement, we can avoid that:Now the
continue
statement actually continues the loop rather than the switch.Quite useful when you have nested loop constructs.
Labels are briefly discussed in conjunction with
break
inside awhile
statement in theabout_Break
help topic