Поделиться через


about_For

Краткое описание

Описывает команду языка, используемую для выполнения инструкций на основе условного теста.

Подробное описание

Оператор For (также известный как For цикл) — это конструкция языка, которую можно использовать для создания цикла, выполняющего команды в блоке команд, в то время как указанное условие вычисляется $true.

Обычное For использование цикла заключается в итерации массива значений и работе с подмножеством этих значений. В большинстве случаев, если требуется выполнить итерацию всех значений в массиве, рекомендуется использовать инструкцию Foreach .

Синтаксис

Ниже показан синтаксис инструкции For .

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

Заполнитель Init представляет одну или несколько команд, выполняемых перед началом цикла. Обычно используется часть инструкции Init для создания и инициализации переменной с начальным значением.

Затем эта переменная будет основой для проверки условия в следующей части инструкции For .

Заполнитель условия представляет часть инструкцииFor, разрешающей$true$falseлогическое значение. PowerShell оценивает условие при For каждом запуске цикла. Если оператор имеет значение $true, команды в выполнении блока команд и инструкция вычисляется снова. Если условие по-прежнему$true, команды в списке инструкций выполняются снова. Цикл повторяется до тех пор, пока условие не станет $false.

Заполнитель "Повторять " представляет одну или несколько команд, разделенных запятыми, которые выполняются при каждом повторе цикла. Как правило, это используется для изменения переменной, тестируемой внутри части инструкции Condition .

Заполнитель списка инструкций представляет набор одной или нескольких команд, выполняемых каждый раз при вводе или повторе цикла. Содержимое списка инструкций окружено фигурными скобками.

Поддержка нескольких операций

Следующие синтаксисы поддерживаются для нескольких операций назначения в инструкции 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"
}

Примечание.

Операции, отличные от предварительных или постовых добавок, могут не работать со всеми синтаксисами.

Для нескольких условий используются логические операторы, как показано в следующем примере.

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 части инструкции и команды, окруженной фигурными скобками в списке инструкций.

Обратите внимание, что предстоящие примеры намеренно показывают код за пределами инструкции For . В последующих примерах код интегрируется в инструкцию For .

Например, следующая For инструкция постоянно отображает значение переменной $i до тех пор, пока вы не будете вручную выйти из команды, нажав клавиши CTRL+C.

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

Дополнительные команды можно добавить в список инструкций, чтобы значение $i увеличивается на 1 при каждом запуске цикла, как показано в следующем примере.

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

Пока команда не завершится, нажав клавиши CTRL+C, эта инструкция будет постоянно отображать значение переменной $i , так как она увеличивается на 1 при каждом запуске цикла.

Вместо того чтобы изменить значение переменной в списке инструкций, For можно использовать часть инструкции Repeat , For как показано ниже.

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

Эта инструкция по-прежнему будет повторяться неограниченно до тех пор, пока не завершите выполнение команды, нажав клавиши CTRL+C.

Вы можете завершить For цикл с помощью условия. Условие можно поместить с помощью части условия инструкцииFor. Цикл For завершается, когда условие вычисляется $false.

В следующем примере цикл выполняется в For то время как значение $i меньше или равно 10.

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

Вместо создания и инициализации переменной за пределами For инструкции эту задачу можно выполнить внутри For цикла с помощью части инструкции For Init.

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 переменная увеличивается на 2 в части For инструкции Repeat.

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 имеют идентификатор рабочего элемента в качестве имени файла. Цикл выполняет итерацию по файлам, чтобы убедиться, что номер идентификатора равен нулю до пяти цифр.

Во-первых, код извлекает список файлов данных рабочих элементов. Они все JSON-файлы, использующие формат <work-item-type>-<work-item-number> для их имени. С помощью объектов сведений о файле, сохраненных в переменной $fileList , их можно отсортировать по имени и увидеть, что при группировке элементов по типу порядок элементов по идентификатору непредвиден.

$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 цикл для итерации по массивам и вывода объекта со следующими свойствами:

  • Индекс представляет текущий индекс в отсортированных массивах.
  • Исходный — это элемент в отсортированного массива исходных имен файлов по текущему индексу.
  • Padded — это элемент в отсортированном массиве отсортированных имен файлов по текущему индексу.
$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

В выходных данных отсортированные рабочие элементы после заполнения находятся в ожидаемом порядке.

См. также