Windows PowerShell предоставляет несколько способов выполнения кода, включая операторы if, for и while. Можно использовать эти три оператора для определения состояний и действий, которые выполняются, когда эти состояния встречаются. Вы даже можете точно установить те действия, которые осуществляются, когда состояние не появляется. .

Условные операторы

Условные операторы if содержат блок кода условия, который заключен в круглые скобки, и блок команд, заключенный в фигурные скобки. Блок условия задает условие, тогда как блок команд задает одно или несколько действий. Когда условие выполняется (в этом случае блок условия выдает значение true), PowerShell запускает блок команд. Когда блок условия выдает значение false, PowerShell игнорирует блок команд.

Например, следующий код инициализирует переменную $files, затем формулирует базовое условие оператора if:

$files = dir c:\archivedfiles\*.txt
if ($files -ne $null)
{
   "There are files in this folder."
   write-host
}

Первая строка присваивает коллекцию текстовых файлов в $files. Предложение if использует переменную $files в своем блоке условия ($files -ne $null), для того чтобы определить, что переменная не должна быть нулевой. Когда есть текстовые файлы, блок условия выдает true, и вступает в дело блок команд, который выводит сообщение There are files in this folder. Когда блок условия выдает значение false, оператор if прекращает работу. В результате никакое сообщение не выводится на экран, если папка не содержит текстовых файлов.

Время от времени вам бывает нужно выполнить особое действие, когда блок условия выдает значение false. Вы можете это сделать, добавив еще оператор else. Этот оператор начинается с ключевого слова else, за которым следует его собственный блок команд. Дополнительный блок команд запускается, когда ни один из блоков условий оператора if не выдает значение true. Взгляните, например, на такой оператор if:

$files = dir c:\archivedfiles\*.doc
if ($files -ne $null)
{
   "There are Word" +
   "files in this folder."
   write-host
}
else
{
   "No Word files in this folder."
   write-host
}

Когда блок условия (($files -ne $null) выдает значение false, блок команд else запускает и выводит на экран сообщение No Word files in this folder.

В этом примере оператор if рассматривает два варианта: содержит папка файлы Microsoft Word и не содержит их. Но, возможно, вы захотите, чтобы оператор обрабатывал больше, чем два сценария. Тогда вы можете добавить несколько операторов elseif (если нужно использовать много операторов elseif, требуется решить, использовать ли оператор переключения switch). Для каждого оператора elseif вы определяете блок условия и блок команд. Когда блок условия выдает true, запускается блок команд.

Например, код в листинге 1 использует операторы elseif, чтобы определить, как много файлов в папке. В этом коде один оператор if помещен в другой. Код начинается с присваивания коллекции файлов в $files. Затем внешний оператор if проверяет, не является ли $files пустой. Я произвожу такую проверку и не использую свойство Count, чтобы определить количество файлов, поскольку я должен предусмотреть случай, если в папке будет только один файл. Свойство Count доступно только тогда, когда в папке два или более файлов. Когда файлов более одного, PowerShell обращается с $files как с массивом, который поддерживает свойство Count. Когда есть только один файл, PowerShell обращается с $files как со скалярной величиной (то есть единственной), а это означает, что свойство Count недоступно.

Когда внешний оператор if обнаруживает, что $files пуста, запускается оператор else из фрагмента В. Блок команд этого оператора выводит сообщение No files in folder. Когда $files не пуста, запускается внутренний оператор if из фрагмента А. Блок условия внутреннего оператора if определяет три состояния: условие if и два условия elseif.

Условие if ($files.count -gt 10) определяет, что число текстовых файлов должно быть более десяти. Когда блок условия выдает true, блок команд выводит сообщение More than 10 files in folder.

Первый оператор elseif ($files.count -gt 7 и $files.count -le 10) определяет, что число текстовых файлов должно быть больше 7, но меньше или равно 10. Когда блок условия выдает true, блок команд выводит сообщение «5-7 files in folder».

Если ни один из блоков условий не выдает значение true, запускается блок команд оператора else. Он выводит сообщение Fewer than 5 files in folder.

Как видно из листинга 1, вы можете вставить оператор if в блок команд другого оператора if, но вы не ограничены только этими типами операторов. Можно, например, вставить оператор foreach в блок команд оператора if, как показано в листинге 2. Foreach-оператор запускается только тогда, когда блок условия оператора if выдает true. Другими словами, когда папка содержит текстовые файлы, оператор foreach будет выполнять цикл по этим текстовым файлам. Каждый раз, когда цикл повторяется, оператор foreach возвращает размер текстового файла, как показано на экране 1.

 

Результаты работы встроенного оператора foreach в операторе if
Экран 1. Результаты работы встроенного оператора foreach в операторе if

Оператор for

Я уже рассказывал о том, как реализовать оператор цикла foreach, чтобы произвести перебор коллекции. Оператор for запускает пошаговый цикл, который повторяется по всей коллекции, как только условие подтверждается. Подобно условным операторам if, операторы for включают блок условия и блок команд. Однако блок условия здесь гораздо сложнее.

Давайте посмотрим па простой пример. Следующий оператор for показывает значения, заданные для переменной $a:

for ($a = 1; $a -le 5; $a++) {$a}

Оператор начинается с ключевого слова for, за которым следует блок условия ($a = 1; $a -le 5; $a++). Блок условия оператора for состоит из трех частей, которые разделены точкой с запятой. Первая часть ($a = 1) инициализирует переменную $a значением 1. Переменная $a обеспечивает базовую, или начальную, величину для других элементов блока кода.

Вторая часть ($a -le 5) — это само условие. В данном случае значение в $a должно быть меньше 5, чтобы получить true. Третья часть ($a++) увеличивает $a на единицу в конце каждого цикла. В итоге оператор будет двигаться через коллекцию, пока значение $a меньше или равно 5. Когда $a равно 6, оператор for прекращает работу. На экране 2 показан простой вывод этого оператора.

 

Результаты работы оператора for при реализации цикла по коллекции
Экран 2. Результаты работы оператора for при реализации цикла по коллекции

В некоторых случаях вы не можете знать количество элементов в коллекции. Код в листинге 3 показывает, как можно использовать оператор for, чтобы произвести итерацию по такой коллекции. Этот код начинается с присваивания коллекции текстовых файлов в переменной $files. Оператор if использует переменную $files и ее свойство Count ($files.count), чтобы проверить число файла. Как уже говорилось, если в коллекции только один файл, PowerShell вернет объект (например, объект System.IO.FileSystemInfo), у которого есть скалярное значение. Если файлов нет, PowerShell не возвращает объект. В любом случае свойство Count не существует. В результате вы получаете пустое значение, если пытаетесь вызвать свойство Count, поэтому можете использовать его как условие в операторе if.

Когда $files.count возвращает значение null, оператор else из фрагмента В проверяет, действительно ли там только один файл. Если файлов там нет, запускается оператор else из фрагмента С.

Когда $files.count не возвращает значение null (то есть PowerShell возвращает объект System.Array, таким образом, свойство Count существует), запускается код из фрагмента А, поскольку есть по меньшей мере два файла. Во фрагменте А код условия цикла внутреннего оператора for использует свойство Count для определения точного количества файлов (то есть элементов) в коллекции. Как только $i становится меньше, чем число элементов, условие выдает true.

Заметьте, что я инициализировал $i с нуля. Я использую нуль, поскольку коллекции, такие как $files, используют как базу для индексации нуль. В блоке команд я применял $i, чтобы установить, какой элемент извлечь из коллекции. Например, в течение первого шага цикла $i равна нулю. Это означает, что $files [$i] — такая же, как $files [0]. На втором шаге цикла $i равно 1, таким образом, значение становится $files [1] и т. д. На экране 3 показаны результаты работы кода, приведенного в листинге 3.

 

Получение списка текстовых файлов и их размеров
Экран 3. Получение списка текстовых файлов и их размеров

Еще следует обратить внимание на то, что вы можете задать имя и тип используемой в программе переменной и инициализировать базовую переменную до запуска оператора for. Например, в листинге 4 переменной $i задано имя и тип, и она инициализирована в строке, выделенной во фрагменте А. Очевидно, что код в этом случае читать легче.

Операторы while

Подобно оператору for, операторы while — это тип цикла, который производит итерации по коллекции. Оператор while, который состоит из блока условия и блока команд, продолжается, пока блок условия не выдаст значение true. Следующий код показывает простой пример того, как он работает:

$count = 0
while ($count -lt 5)
{
   $count++
   "The count is
   $count."
}

Первая строка кода инициализирует $count нулем. Эта переменная используется как база или начальная величина для организации цикла. Блок условия ($count -lt 5) определяет, что $count должно быть меньше 5.

Когда блок условия выдает true, запускается блок команд. Первый оператор в блоке команд увеличивает $count на 1. Второй оператор выводит строку, которая показывает текущее значение $count, как мы видим в результатах:

The count is 1.
The count is 2.
The count is 3.
The count is 4.
The count is 5.

Заметим, что, когда $count равна 4 в блоке условия, блок команд увеличивает $count на 1 и выводит в итоге значение 5. И только на следующем шаге блок условия вернет false и тем самым остановит цикл while.

Иногда вы можете не знать количество элементов в коллекции, по которой происходит повторение цикла. В подобной ситуации можно использовать свойство Count для возвращения значения:

$proc = Get-Process
$count = 0
while ($count -lt
$proc.count)
{
   "The" +
      $proc [$count].name +
      "process uses" +
      $proc [$count].handles +
      "handles."
   $count ++
}

Этот код вначале присваивает результаты команды Get-Process переменной $proc. Эта команда возвращает список процессов, запущенных на локальной системе. Блок условия в цикле while определяет, что величина в $сount должна быть меньше, чем общее количество процессов ($proc.count). На экране 4 показаны результаты запуска этого кода. Вы можете использовать переменную $proc, чтобы найти не только количество процессов, но и имя каждого процесса и количество дескрипторов.

 

Получение списка процессоров и числа их дескрипторов
Экран 4. Получение списка процессоров и числа их дескрипторов

В этой статье я рассказал об условных операторах if, for и while. Эти операторы, наряду с foreach- и командой ForEach-Object, дают нам возможность выбора инструментов для реализации управления исполнением кода. Вы можете использовать эти операторы и пытаться комбинировать их разными способами, например добавляя условные операторы if к операторам foreach.

Листинг 1. Оператор if, содержащий оператор elseif

$files = dir c:\archivedfiles\*.txt
if ($files -ne $null)

Начало фрагмента А
{
  if ($files.count -gt 10)
  {
    "More than 10 files in folder."
    write-host
  }
  elseif ($files.count -gt 7 -and
    $files.count -le 10)
  {
    "8-10 files in folder."
    write-host
  }
  elseif ($files.count -gt 4 -and
    $files.count -le 7)
  {
    "5-7 files in folder."
    write-host
  }
  else
  {
    "Fewer than 5 files in folder."
    write-host
  }
}
Конец фрагмента A

Начало фрагмента B
else
{
  "No files in folder."
  write-host
}
Конец фрагмента B

Листинг 2. Оператор if со встроенным оператором foreach

$files = dir c:\archivedfiles\*.txt
if ($files -ne $null)
{
  write-host
  foreach ($file in $files)
  {
    "The $file file is " +
      $file.length + " bytes."
  }
  write-host
}
else
{
  "No files in this folder."
  write-host
}

Листинг 3. Оператор for

$files = dir c:\archivedfiles\*.txt
if ($files.count -ne $null)

Начало фрагмента A
{
  for ($i = 0; $i -lt $files.count;
    $i++)
  {
    $files[$i].name + " = " +
      $files[$i].length + " bytes"
  }
  write-host
}
Конец фрагмента A

Начало фрагмента B
elseif ($files -ne $null `
    -and $files.count -eq $null)
{
  $files.name + " = " +
    $files.length + " bytes"
  write-host
}
Конец фрагмента B

Начало фрагмента C
else
{
  "No text files in this folder."
  write-host
}
Конец фрагмента C

Листинг 4. Код для объявления и инициализации $i перед оператором for

$files = dir c:\archivedfiles\*.txt

Начало фрагмента A
$i = 0
Конец фрагмента A

if ($files.count -ne $null)
{
  for ($i; $i -lt $files.count;
    $i++)
  {
    $files[$i].name + " = " +
      $files[$i].length + " bytes"
  }
  write-host
}
elseif ($files -ne $null `
    -and $files.count -eq $null)
{
  $files.name + " = " +
    $files.length + " bytes"
  write-host
}
else
{
  "No text files in this folder."
  write-host
}

Роберт Шелдон (contact@rhsheldon.com) — технический консультант и автор книг по технологиям Microsoft Windows и базам данных