Что означает $ _ в PowerShell?

226

Я много видел в PowerShell следующее, но что именно он делает?

$_
Михей
источник
5
Ответ на этот вопрос, конечно же, дан по одному специальному токену, но для настенной диаграммы, иллюстрирующей все специальные токены PowerShell, взгляните на Полное руководство по пунктуации PowerShell
Майкл Соренс,

Ответы:

171

Это переменная для текущего значения в конвейере, которая вызывается $PSItemв Powershell 3 и новее.

1,2,3 | %{ write-host $_ } 

или

1,2,3 | %{ write-host $PSItem } 

Например, в приведенном выше коде %{}блок вызывается для каждого значения в массиве. $_Или $PSItemпеременная будет содержать текущее значение.

JaredPar
источник
42
Это не обязательно связано с конвейером. Это скорее «текущий аргумент для текущего исполняемого блока скрипта». Например, в то время как вы можете использовать его просто отлично ForEach-Objectили Where-Objectвы не можете использовать его в чем-то вроде Get-Foo|Add-Member NoteProperty Bar ($_.SomeProperty)- там задействован конвейер, но нет блока скрипта и, следовательно, нет $_. (При этом справка PowerShell также относится к конвейеру $_. Запутывает.)
Joey
@Joey, вы можете использовать $ _ в вашем примере. Get-Foo | Add-Member -Type NoteProperty -Name Bar -Value $_.SomeProperty
Ксалори
@Xalorous: То, что это не приводит к ошибке, не означает, что это работает: Get-ChildItem | Add-Member -Type NoteProperty -Name Bar -Value $_.Name -PassThru | Select Bar... Ну, это может работать, если у вас есть $_область действия, в которой вы выполняете этот конвейер. Но это сильно отличается от того, что вы обычно имеете в виду, когда пытаетесь написать что-то подобное.
Joey
@Joey $_в том, что вы написали, по какой-то причине не перебирает все объекты. Попробуйте это вместо этого. gci | % { $_ | add-member -Type NoteProperty -Name Bar -Value $_.name -PassThru } | Select Bar, Я подозреваю, что наличие gci | cmdletбез явного foreach собирает результаты gci и передает массив командлету. Однако массив является объектом, поэтому он добавляет свойство к объекту массива. Массив не имеет свойства name, поэтому значение, присвоенное $ _. Bar, равно $ null. Суть в том, что $ _ широко используется с конвейеризацией. Не нужно% {}, чтобы пройти через это новый.
Ксалори
Рабочая версия с удаленным дополнительным конвейером. gci | % { add-member -InputObject $_ -Type NoteProperty -Name Bar -Value $_.name -PassThru } | Select Bar
Ксалори
37

Я думаю, что самый простой способ думать об этой переменной, как входной параметр в лямбда-выражении в C #. Т.е. $_аналогично xв x => Console.WriteLine(x)анонимной функции в C #. Рассмотрим следующие примеры:

PowerShell:

1,2,3 | ForEach-Object {Write-Host $_}

Печать:

1
2
3

или

1,2,3 | Where-Object {$_ -gt 1}

Печать:

2
3

И сравните это с синтаксисом C #, используя LINQ:

var list = new List<int> { 1, 2, 3 };
list.ForEach( _ => Console.WriteLine( _ ));

Печать:

1
2
3

или

list.Where( _ => _ > 1)
    .ToList()
    .ForEach(s => Console.WriteLine(s));

Печать:

2
3
Сергей Тепляков
источник
6
В C # не используйте в _качестве входного параметра в лямбду. _иногда используется, когда параметры игнорируются, вместо этого используйте x. stackoverflow.com/questions/424775/…
Карлос Муньос
28

Согласно этому сайту, это ссылка this, в основном, в петлях.

$ _ (подчеркивание доллара) токен «ЭТО». Обычно относится к элементу внутри цикла foreach. Задача: Распечатать все элементы в коллекции. Решение. ... | foreach {Write-Host $ _}

Ikke
источник
3
thisдовольно запутанный термин для $_переменной. В ООП это обычно относится к классу, а не к переменной.
ɔɯǝɹ
1
@remco, особенно когда PS v5 добавляет переменную $ this для использования в классах.
Ксалори
1

$ _ - это переменная, которая перебирает каждый объект / элемент, переданный из предыдущего | (Труба).

Билл
источник
1

$_переменная, создаваемая системой обычно внутри блочных выражений, на которые ссылаются командлеты, используемые с конвейером, такие как Where-Objectи ForEach-Object.

Но его можно использовать и в других типах выражений, например, в Select-Objectсочетании со свойствами выражений. Get-ChildItem | Select-Object @{Name="Name";Expression={$_.Name}}, В этом случае $_объект представляет передаваемый элемент, но могут существовать несколько выражений.

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

Ближайшая аналогия c # и java - это выражение lamda. Если вы разберетесь с PowerShell до основ, то все будет блоком скрипта, включая файл скрипта a, функции и командлеты. Вы можете определить свои собственные параметры, но в некоторых случаях они создаются системой для вас, которая представляет элемент ввода для обработки / оценки . В этих ситуациях автоматическая переменная есть $_.

Алекс Сарафян
источник