about_For

简短说明

介绍可用来基于条件测试运行语句的语言命令。

长说明

For 语句(也称为 For 循环)是一种用于创建循环的语言构造,该循环在指定条件的计算结果为 $true 时运行命令块中的命令。

For 循环的典型用法是循环访问值数组,并对这些值的子集进行操作。 在大多数情况下,如果要循环访问数组中的所有值,请考虑使用 Foreach 语句。

语法

以下内容介绍 For 语句的语法。

for (<Init>; <Condition>; <Repeat>)
{
    <Statement list>
}

Init 占位符表示在循环开始前运行的一个或多个命令。 通常使用语句的 Init 部分来创建和初始化具有起始值的变量

此变量随后将是 For 语句下一部分中要测试的条件的基础。

Condition 占位符表示解析为$true $false 布尔值的语句部分For。 每次运行 For 循环时,PowerShell 都会对条件进行计算。 如果语句为 $true,则会运行命令块中的命令,并再次对该语句进行计算。 如果条件仍为 $true,则语句列表中的命令将再次运行。 此循环会重复运行,直到条件变为 $false

Repeat 占位符表示每次重复运行循环时执行的一个或多个命令(用逗号分隔)。 通常,此占位符用于修改在语句的 Condition 部分测试的变量

Statement list 占位符表示每次进入循环或重复运行循环时运行的一组命令(一个或多个命令)。 Statement list 的内容用大括号括起来

支持多个操作

Init 语句中的多个赋值操作支持以下语法

# Comma separated assignment expressions enclosed in parentheses.
for (($i = 0), ($j = 0); $i -lt 10; $i++)
{
    "`$i:$i"
    "`$j:$j"
}

# Sub-expression using the semicolon to separate statements.
for ($($i = 0;$j = 0); $i -lt 10; $i++)
{
    "`$i:$i"
    "`$j:$j"
}

Repeat 语句中的多个赋值操作支持以下语法

# Comma separated assignment expressions.
for (($i = 0), ($j = 0); $i -lt 10; $i++, $j++)
{
    "`$i:$i"
    "`$j:$j"
}

# Comma separated assignment expressions enclosed in parentheses.
for (($i = 0), ($j = 0); $i -lt 10; ($i++), ($j++))
{
    "`$i:$i"
    "`$j:$j"
}

# Sub-expression using the semicolon to separate statements.
for ($($i = 0;$j = 0); $i -lt 10; $($i++;$j++))
{
    "`$i:$i"
    "`$j:$j"
}

注意

除前递增或后递增以外的操作可能不适用于所有语法。

对于多个 Conditions,请使用逻辑运算符,如下例所示

for (($i = 0), ($j = 0); $i -lt 10 -and $j -lt 10; $i++,$j++)
{
    "`$i:$i"
    "`$j:$j"
}

有关详细信息,请参阅 about_Logical_Operators

语法示例

For 语句要求至少用括号将语句的 Init、Condition 和 Repeat 部分括起来,并在语句的 Statement list 部分将命令用大括号括起来

请注意,接下来的示例有意显示 For 语句之外的代码。 在后面的示例中,代码集成到 For 语句中。

例如,以下 For 语句持续显示 $i 变量的值,直到你按 Ctrl+C 手动中断命令。

$i = 1
for (;;)
{
    Write-Host $i
}

可向 Statement list 添加其他命令,使得每次运行循环时 $i 的值都递增 1,如下例所示。

for (;;)
{
    $i++; Write-Host $i
}

此语句将持续显示 $i 变量的值,直到你按 Ctrl+C 中断命令为止,因为每次运行循环时该变量的值都会递增 1。

可使用 For 语句的 Repeat 部分,而不必更改 For 语句的 Statement list 部分的变量值,如下所示

$i=1
for (;;$i++)
{
    Write-Host $i
}

此语句仍将无限期重复,直到你按 Ctrl+C 中断命令。

可使用一个条件来终止 For 循环。 可使用 For 语句的 Condition 部分放置条件。 当条件的计算结果为 $false 时,For 循环会终止。

在下例中,For 循环将在 $i 的值小于或等于 10 时运行。

$i=1
for(;$i -le 10;$i++)
{
    Write-Host $i
}

可使用 For 语句的 Init 部分在 For 循环中执行此任务,而不是在 For 语句外部创建和初始化变量

for($i=1; $i -le 10; $i++){Write-Host $i}

可使用回车符而不是分号来分隔 For 语句的 Init、Condition 和 Repeat 部分。 以下示例演示了使用此替代语法的 For

for ($i = 0
  $i -lt 10
  $i++){
  $i
}

For 语句的这种替代形式适用于 PowerShell 脚本文件和 PowerShell 命令提示符。 但是,在命令提示符处输入交互式命令时,使用带分号的 For 语句语法会更容易。

For 循环比 Foreach 循环更灵活,因为它允许使用模式来递增数组或集合中的值。 在下例中,$i 变量在 For 语句的 Repeat 部分递增 2

for ($i = 0; $i -le 20; $i += 2)
{
    Write-Host $i
}

For 循环也可写在一行上,如下例所示。

for ($i = 0; $i -lt 10; $i++) { Write-Host $i }

功能示例

以下示例演示如何使用 For 循环循环访问文件数组并重命名它们。 文件夹中的文件 work_items 具有其工作项 ID 作为文件名。 循环循环遍历文件,以确保 ID 号为零填充为五位数字。

首先,代码检索工作项数据文件的列表。 它们是使用其名称格式 <work-item-type>-<work-item-number> 的所有 JSON 文件。 将文件信息对象保存到 $fileList 变量后,可以按名称对它们进行排序,并查看当项按类型分组时,按 ID 对项排序是意外的。

$fileList = Get-ChildItem -Path ./work_items
$fileList | Sort-Object -Descending -Property Name
bug-219.json
bug-41.json
bug-500.json
bug-697.json
bug-819.json
bug-840.json
feat-176.json
feat-367.json
feat-373.json
feat-434.json
feat-676.json
feat-690.json
feat-880.json
feat-944.json
maint-103.json
maint-367.json
maint-454.json
maint-49.json
maint-562.json
maint-579.json

为了确保可以按字母顺序对工作项进行排序,工作项编号需要为零填充。

代码首先使用最长的数字后缀搜索工作项来执行此操作。 它使用 for 循环循环遍历文件,使用索引访问数组中的每个文件。 它将每个文件名与正则表达式模式进行比较,以将工作项编号提取为字符串而不是整数。 然后,它会比较工作项编号的长度以查找最长的数字。

# Default the longest numeral count to 1, since it can't be smaller.
$longestNumeralCount = 1

# Regular expression to find the numerals in the filename - use a template
# to simplify updating the pattern as needed.
$patternTemplate = '-(?<WorkItemNumber>{{{0},{1}}})\.json'
$pattern         =  $patternTemplate -f $longestNumeralCount

# Iterate, checking the length of the work item number as a string.
for (
    $i = 0                 # Start at zero for first array item.
    $i -lt $fileList.Count # Stop on the last item in the array.
    $i++                   # Increment by one to step through the array.
) {
    if ($fileList[$i].Name -match $pattern) {
        $numeralCount = $Matches.WorkItemNumber.Length
        if ($numeralCount -gt $longestNumeralCount) {
            # Count is higher, check against it for remaining items.
            $longestNumeralCount = $numeralCount
            # Update the pattern to speed up the search, ignoring items
            # with a smaller numeral count using pattern matching.
            $pattern = $patternTemplate -f $longestNumeralCount
        }
    }
}

了解工作项的最大数字计数后,可以循环访问文件以根据需要重命名它们。 下一个代码片段再次循环访问文件列表,并根据需要填充它们。 它使用另一个正则表达式模式仅处理数字计数小于最大值的文件。

# Regular expression to find the numerals in the filename, but only if the
# numeral count is smaller than the longest numeral count.
$pattern = $patternTemplate -f 1, ($longestNumeralCount - 1)
for (
    $i = 0                 # Start at zero for first array item.
    $i -lt $fileList.Count # Stop on the last item in the array.
    $i++                   # Increment by one to step through the array.
) {
    # Get the file from the array to process
    $file = $fileList[$i]

    # If the file doesn't need to be renamed, continue to the next file
    if ($file.Name -notmatch $pattern) {
        continue
    }

    # Get the work item number from the regular expression, create the
    # padded string from it, and define the new filename by replacing
    # the original number string with the padded number string.
    $workItemNumber = $Matches.WorkItemNumber
    $paddedNumber   = "{0:d$longestNumeralCount}" -f $workItemNumber
    $paddedName     = $file.Name -replace $workItemNumber, $paddedNumber

    # Rename the file with the padded work item number.
    $file | Rename-Item -NewName $paddedName
}

重命名文件后,可以再次检索文件列表,并按名称对旧文件和新文件进行排序。 以下代码片段再次检索文件以保存在新数组中,并与初始对象集进行比较。 然后,它将这两个文件数组进行排序,将排序的数组保存到新的变量 $sortedOriginal$sortedPadded。 最后,它使用循环 for 循环访问数组并输出具有以下属性的对象:

  • 索引 表示排序数组中的当前索引。
  • Original 是当前索引处原始文件名的排序数组中的项。
  • 填充是当前索引处填充文件名的已排序数组中的项。
$paddedList = Get-ChildItem -path ./work_items

# Sort both file lists by name.
$sortedOriginal = $fileList    | Sort-Object -Property Name
$sortedPadded   = $renamedList | Sort-Object -Property Name

# Iterate over the arrays and output an object to simplify comparing how
# the arrays were sorted before and after padding the work item numbers.
for (
  $i = 0
  $i -lt $fileList.Count
  $i++
) {
    [pscustomobject] @{
        Index    = $i
        Original = $sortedOriginal[$i].Name
        Padded   = $sortedPadded[$i].Name
    }
}
Index Original       Padded
----- --------       ------
    0 bug-219.json   bug-00041.json
    1 bug-41.json    bug-00219.json
    2 bug-500.json   bug-00500.json
    3 bug-697.json   bug-00697.json
    4 bug-819.json   bug-00819.json
    5 bug-840.json   bug-00840.json
    6 feat-176.json  feat-00176.json
    7 feat-367.json  feat-00367.json
    8 feat-373.json  feat-00373.json
    9 feat-434.json  feat-00434.json
   10 feat-676.json  feat-00676.json
   11 feat-690.json  feat-00690.json
   12 feat-880.json  feat-00880.json
   13 feat-944.json  feat-00944.json
   14 maint-103.json maint-00049.json
   15 maint-367.json maint-00103.json
   16 maint-454.json maint-00367.json
   17 maint-49.json  maint-00454.json
   18 maint-562.json maint-00562.json
   19 maint-579.json maint-00579.json

在输出中,填充后排序的工作项按预期顺序排列。

另请参阅