about_Foreach示例:PowerShell中的cmd子例程语法?

时间:2017-09-06 14:19:38

标签: powershell syntax powershell-v5.0

this about page中,有一个代码块(下面)显示$ForEach自动变量,但它也有批处理子程序的语法。我找不到关于这段代码如何运行或语言结构被调用的文档。我相信这是PowerShell v5的补充,但阅读发行说明也没有帮助我。 :tokenLoop foreach ($token in $tokens)代表什么?

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
    }
  }
}

1 个答案:

答案 0 :(得分:4)

在PowerShell 版本3.0及更高版本中(至少从版本2.0开始),以下语句类型可选地标记为

  • switch
  • foreach
  • for
  • while
  • do

现在,这是什么意思?这意味着您可以将标签名称作为参数提供给标记语句正文中的breakcontinue语句,并使流控制应用于标签指示的语句。

考虑这个例子:

foreach($Name in 'Alice','Bob','Charlie'){
    switch($Name.Length){
        {$_ -lt 4} {
            # We don't have time for short names, go to the next person
            continue
        }
        default {
            Write-Host "$Name! What a beautiful name!"
        }
    }

    Write-Host "Let's process $Name's data!"
}

您可能会期待"让我们来处理[...]"字符串只显示两次,因为我们continue的情况Bob,但由于直接父语句是switch,它实际上并不适用于{{1}声明。

现在,如果我们可以明确声明我们想要继续foreach循环而不是switch语句,我们可以避免这种情况:

foreach

现在:outer_loop foreach($Name in 'Alice','Bob','Charlie'){ switch($Name.Length){ {$_ -lt 4} { # We don't have time for short names, go to the next person continue outer_loop } default { Write-Host "$Name! What a beautiful name!" } } Write-Host "Let's process $Name's data!" } 语句实际上继续循环而不是切换。

当你有嵌套的循环结构时非常有用。

about_Break help topic

中的continue声明中与break一起简要讨论了标签