Очень часто нам приходится совершать некую операцию над группой объектов – файлов, процессов, текстовых строк, и т.д. Делать это в PowerShell можно разными способами. Например For:
# Получаем объекты представляющие файлы в переменную $files $Files = dir C:\root\test # С помощью for: # 1) объявляем переменную $i, и присваиваем ей значение 0 # 2) указываем условие повторения цикла($i меньше количества файлов) # 3) указываем что после каждого выполнения цикла надо увеличить $i на еденицу for ($i=0; $i -lt $files.Count; $i++) { # Пока условие удовлетворяется, вызываем утилиту md5.exe, передавая ей в # качестве аргумента элемент массива файлов под номером $i (отсчет идет с 0) md5.exe $files[$i] }
И вот результат:
For очень популярен, присутствует во множестве языков, но тем не менее обладает некоторыми недостатками. Во первых это необходимость использования временной переменной для перебора, во вторых – излишняя сложность конструкции. Гораздо проще для перебора группы объектов использовать ForEach:
# Получаем объекты представляющие файлы в переменную $files $Files = dir C:\root\test # Каждый объект из $Files по очереди помещяется в переменную $File ForEach ($File in $Files) { # ... и выполняется блок кода... md5.exe $File }
Или еще короче:
Способ отличный, но тоже не лишен недостатков. Обычно работая в консоли я сначала выполняю команду dir или get-*, для того чтобы посмотреть на список объектов, а затем уже хочу обработать их. Для использования ForEach мне пришлось бы возвращаться в начало строки, дописывать там Foreach ($obj in ( затем идет код получения объектов, затем закрывающие скобки и затем уже код для выполнения. Не слишком удобно для быстрой работы. Но к счастью есть командлет Foreach-Object. В него можно просто перенаправить полученные объекты, и указать блок кода для выполнения. При этом даже не нужно указывать имя для временного объекта – он всегда будет представлен под именем $_
Так как этот командлет предназначен в первую очередь для интерактивной работы, то у него есть два псевдонима: ForEach (хоть и почти идентичен ранее упомянутому ключевому слову, путать их не стоит) и % (знак процента). Вот это уже гораздо удобнее для работы в шелле, хоть и выглядит страшновато для непосвященных
Удобнее может быть только использование PowerShell’овских командлетов или скриптов умеющих обрабатывать объекты получаемые по конвейеру. Тут уже не надо никаких For и Foreach
На самом деле я изложил тут лишь одно применение переменной $_ (кстати она называется “Default variable”), хоть и наиболее популярное. $_ используется еще во многих местах, обычно представляя “текущий объект”. Но думаю теперь вам будет проще понять и эти случаи. Например в командлете Where-Object $_ исполняет ту же роль что и в ForeEach-Object – содержит текущий объект конвейера. А в блоке обработки ошибок (trap), за $_ будет скрываться объект текущей ошибки.









26.9.2008 в 10:11
А как тогда определить разницу между двумя ForEach? Первый использует круглые скобки, а второй фигурные?
26.9.2008 в 10:16
2 Артём:
Парсер PowerShell’а отличает следующим образом: если в конвейере, то командлет Foreach-Object, а если в начале блока – keyword.
То есть например конструкция
ForEach -InputObject (1,2,3) {$_}
вернет следующую ошибку:
Missing opening ‘(‘ after keyword ‘foreach’.
а вот
ForEach-Object -InputObject (1,2,3) {$_}
отработает правильно. Впрочем на практике это не мешает совершенно.