Мощный урок PowerShell: это не обычная переменная

Опубликовано: 16 Марта, 2023
Мощный урок PowerShell: это не обычная переменная

Если вы следите за моей работой на этом сайте, то знаете, что я пишу много контента, связанного с PowerShell. Одно из выражений, которые я регулярно использую в своих сценариях PowerShell, — это точка подчеркивания со знаком доллара (или $_. ). Недавно кто-то спросил меня, что означают эти символы, и я понял, что никогда не тратил время, чтобы объяснить значение этой серии символов или почему они используются так часто. Поэтому я хочу воспользоваться возможностью сделать это сейчас.

Интересная вещь о $_. заключается в том, что первый из этих трех символов является знаком доллара. В PowerShell размещение знака доллара перед словом (или рядом символов) означает, что слово является переменной. Если, например, я хочу присвоить свое имя переменной, я могу использовать такую команду:

$Name = 'Брайен'

Точно так же PowerShell позволяет отображать всю командную строку в переменную. Я мог бы, например, создать переменную с именем $Processes и установить ее равной командлету Get-Process, как показано ниже:

$Процессы = Получить-Процесс

Почему $_. не обычная переменная

Дело в том, что знак доллара в $_. указывает, что $_. является переменной. Однако это не обычная переменная. Вместо этого его часто называют переменной в конвейере.

В PowerShell слово «конвейер» обычно относится к серии команд, объединенных вместе. Отдельные команды отделяются друг от друга с помощью символа вертикальной черты (отсюда и название конвейера). Когда команды объединяются в конвейер, выходные данные одной команды используются в качестве входных данных для следующей команды в последовательности.

В качестве более конкретного примера рассмотрим командлет Get-Process. Этот командлет извлекает список процессов, запущенных на компьютере. Затем вы можете использовать символ вертикальной черты, чтобы рассматривать список процессов как ввод для следующей команды в серии. Например, вы можете сузить список, чтобы просмотреть некоторые конкретные процессы. Для этого вы можете направить выходные данные команды Get-Process в командлет Where-Object, который может фильтровать эти выходные данные. Вот пример.

Get-процесс | Where-Object {$_.ProcessName -eq 'dllhost'}

Эта команда показывает все процессы, имя которых равно dllhost. Вы можете увидеть команду и ее вывод, показанные на изображении ниже.

Вы заметите, что команда, которую я здесь использую, включает переменную в конвейер. Прежде чем я начну анализировать команду и объяснять, как она и переменная в конвейере работают, я хочу прояснить одну вещь. Хотя $_. обычно упоминается как переменная конвейера, ничто не мешает вам использовать обычную переменную в конвейере. PowerShell чрезвычайно гибок в том, что касается способов использования переменных.

Если вы вернетесь к предыдущему снимку экрана, вы заметите, что информация, представленная в выходных данных, разделена на ряд столбцов, и каждый из этих столбцов имеет имя. Часть команды Where-Object просматривает определенный столбец (ProcessName) и проверяет, равен ли он (-EQ) определенному значению (dllhost). Так где же вступает в игру переменная конвейера?

Переменная конвейера по существу действует как ярлык. Ранее я упоминал, что можно присвоить команду переменной. Если вы посмотрите на изображение ниже, вы увидите, что я сопоставил команду Get-Process с переменной с именем $Processes. Если бы я просто набрал имя переменной, PowerShell выдал бы тот же вывод, как если бы я вручную выполнил командлет Get-Process, что вы также можете видеть на рисунке.

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

Изображение 4372
Имея это в виду, рассмотрим нашу исходную команду:

Get-процесс | Where-Object {$_.ProcessName -eq 'dllhost'}

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

Итак, если это так, то мы должны иметь возможность наблюдать аналогичную функциональность из переменной, которую мы уже объявили ($Processes). Поскольку мы установили переменную $Processes равной командлету Get-Process, мы можем заменить часть Get-Process команды выше именем переменной. Таким образом, команды будут выглядеть так:

$Processes=Процесс получения
$Процессы | Where-Object {$_.ProcessName -eq 'dllhost'}

Вы можете увидеть вывод ниже.

Изображение 4373
Итак, в этой команде $_. переменная действует как ярлык. Мы ссылаемся на переменную $Processes один раз, а затем используем $_. в остальной части команды вместо того, чтобы вводить полное имя переменной. Но просто чтобы показать вам, что конвейерная переменная — это всего лишь ярлык для ссылки на переменную по имени, взгляните на снимок экрана ниже. Здесь я получил вывод, очень похожий на результат моей исходной команды, сославшись на $Processes.ProcessName.
Изображение 4374

Сократите путь

Как видите, $_. по сути, это просто ярлык, который избавляет вас от необходимости повторно вводить имя переменной в команде конвейера. Тем не менее, стоит отметить, что конвейерная переменная и полное выражение переменной не являются взаимозаменяемыми. Если бы вы использовали:

$Процессы | Где-объект {$Processes.ProcessName -eq 'dllhost'}

Вместо:

$Процессы | Where-Object {$_.ProcessName -eq 'dllhost'}

Выходные данные не будут фильтроваться в соответствии с запросом.