Зачем это нужно?
Это необходимо, поскольку метод BorderAround
имеет возвращаемое значение, а в PowerShell любая командаили выражение ...
, которое выводит (возвращает) данные , равное , неявно выводит в свой (успешный) выходной поток , которыйпо умолчанию идет на хост , который обычно является консольным окном (терминал), в котором выполняется сеанс PowerShell.
То есть данные отображаются в консоли/ терминал, , если это:
- захвачено (
$var = ...
) - отправлено по конвейеру для дальнейшей обработки (
... | ...
; последний сегмент конвейеракоманда может выдавать или не выводить сама) - перенаправлено (
... >
)
или любая их комбинация.
То есть:
$range.BorderAround(1, -4138)
является (более эффективным) сокращением для:
Write-Output $range.BorderAround(1, -4138)
(Явное использование Write-Output
редко требуется.)
Поскольку вы надеваетене хочуна выходе вы должны подавить это , для которого у вас есть несколько вариантов:
$null = ...
[void] (...)
... > $null
... | Out-Null
$null = ...
может быть лучшим общим выбором , потому что:
- передает намерение подавить вперед
[void] = (...)
делает это тоже,но часто требует, чтобы вы приложили остальную часть утверждения в (...)
по синтаксическим причинам;например, [void] 1 + 2
не работает должным образом, только [void] (1 + 2)
- он хорошо работает как с выходными данными command (например,
$null = Get-AdUser ...
), так и выражение вывод (например, $null = $range.BorderAround(1, -4138)
).
И наоборот, избегать ... | Out-Null
, потому что обычно он намного медленнее (за исключением вывода выражения в PowerShell) Core ).
Однако, , если вам нужно отключить все выходных потоков - не только успех вывод, но также и ошибки, подробный вывод, ... - вы должны использовать *> $null
Почему PowerShell производит вывод неявно?
Как shell , Выходное поведение PowerShell основано на потоков , как в традиционных оболочках, таких как cmd.exe
или Bash.(Хотя традиционные оболочки имеют 2 выходных потоков - stdout и stderr - PowerShell имеет 6 , чтобы обеспечить более сложные функциональные возможности - см. about_Redirection .)
Командлет, сценарий или функция могут записывать в выходные потоки столько раз, сколько пожелают, и такой вывод обычно мгновенно доступен для отображения, но особенно дляпотенциальные потребители , что обеспечивает потоковую обработку по одному, которую конвейер обеспечивает .
Это отличается от традиционного языки программирования , выходное поведение которых основано на возвращаемых значениях , обычно предоставляемых через ключевое слово return
, которое связывает выходные данные (возвращаемое значение) с управлением потоком (выход из области действия ивернитесь к вызывающей стороне).
- Часто ловушкой можно ожидать, что оператор PowerShell
return
будет действовать так же, но это не так: return <val>
является просто синтаксическим сахаром для <val>; return
, т.е.,неявный вывод <val>
с последующим безусловным возвратом управления вызывающей стороне;в частности, использование return
делает не исключающим генерацию вывода из более ранних операторов в той же области.
В отличие отдля традиционных оболочек PowerShell не требует явной команды потока записи для вывода для получения вывода :
ХотяPowerShell имеет аналог echo
, а именно Write-Output
, его использование редко требуется.
- Среди редких случаев, когда полезно
Write-Output
, можно предотвратить перечисление коллекции при выводе с -NoEnumerate
или использовать общий параметр -OutVariable
для обоих выходных данных и записать его в переменную (которая обычно требуется только для выражений , поскольку сами командлеты и расширенные функции / сценарии поддерживают -OutVariable
).
неявное поведение вывода :
Пример:
# Define a function that takes an array of integers and
# outputs their hex representation (e.g., '0xa' for decimal 10)
function Get-HexNumber {
param([int[]] $numbers)
foreach ($i in $numbers) {
# Format the integer at hand
# *and implicitly output it*.
'0x{0}' -f $i.ToString('x')
}
}
# Call the function with integers 0 to 16 and loop over the
# results, sleeping 1 second between numbers.
Get-HexNumber (0..16) | ForEach-Object { "[$_]"; Start-Sleep 1 }
Выше приведено следующее:
[0x0]
# 1-second pause
[0x1]
# 1-second pause
[0x2]
...
[0x10]
Это демонстрирует аспект потоковой передачи поведения: вывод Get-HexNumber
доступен для вызова командлета ForEach-Object
в процессе производства , а не после выхода Get-HexNumber
.