Непонятные штуки — $_ и %

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

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

# Получаем объекты представляющие файлы в переменную $files
$Files = dir C:\root\test
# Каждый объект из $Files по очереди помещяется в переменную $File
ForEach ($File in $Files)
{
    # ... и выполняется блок кода...
    md5.exe $File
}

Или еще короче:

foreach

Способ отличный, но тоже не лишен недостатков. Обычно работая в консоли я сначала выполняю команду dir или get-*, для того чтобы посмотреть на список объектов, а затем уже хочу обработать их. Для использования ForEach мне пришлось бы возвращаться в начало строки, дописывать там Foreach ($obj in ( затем идет код получения объектов, затем закрывающие скобки и затем уже код для выполнения. Не слишком удобно для быстрой работы. Но к счастью есть командлет Foreach-Object. В него можно просто перенаправить полученные объекты, и указать блок кода для выполнения. При этом даже не нужно указывать имя для временного объекта — он всегда будет представлен под именем $_😉

foreachobject

Так как этот командлет предназначен в первую очередь для интерактивной работы, то у него есть два псевдонима: ForEach (хоть и почти идентичен ранее упомянутому ключевому слову, путать их не стоит) и % (знак процента). Вот это уже гораздо удобнее для работы в шелле, хоть и выглядит страшновато для непосвященных😉

fe

Удобнее может быть только использование PowerShell’овских командлетов или скриптов умеющих обрабатывать объекты получаемые по конвейеру. Тут уже не надо никаких For и Foreach😉

gc

На самом деле я изложил тут лишь одно применение переменной $_ (кстати она называется «Default variable»), хоть и наиболее популярное. $_ используется еще во многих местах, обычно представляя «текущий объект». Но думаю теперь вам будет проще понять и эти случаи. Например в командлете Where-Object $_ исполняет ту же роль что и в ForeEach-Object — содержит текущий объект конвейера. А в блоке обработки ошибок (trap), за $_ будет скрываться объект текущей ошибки.

Опубликовано в Learn, PowerShell, Scripting, Tips. 2 комментария »

комментария 2 to “Непонятные штуки — $_ и %”

  1. Артём Says:

    А как тогда определить разницу между двумя ForEach? Первый использует круглые скобки, а второй фигурные?

  2. Xaegr Says:

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


Обсуждение закрыто.

%d такие блоггеры, как: