Что я должен использовать: "Write-Host", "Write-Output" или "[console]::WriteLine"?
Я пытаюсь справиться с PowerShell. Простая вещь, которую я изо всех сил пытаюсь решить, - то, что, кажется, есть много различных способов вывести сообщения. Что я должен использовать и в чем разница, и есть ли обычный способ сделать это?
Я также заметил, что если я использую:
write-host "count=" + $count
+
включается в вывод. Почему это? Разве выражение не должно быть оценено, чтобы произвести единственную объединенную строку прежде, чем это будет записано?
7 ответов
Write-Output
следует использовать, когда вы хотите отправить данные по конвейеру, но не обязательно хотите отобразить их на экране. Конвейер в конце концов напишет это out-default
если больше ничего не использует это сначала. Write-Host
следует использовать, когда вы хотите сделать наоборот. [console]::WriteLine
по сути то, что Write-Host
делает за кулисами.
Запустите этот демонстрационный код и проверьте результат.
function Test-Output {
Write-Output "Hello World"
}
function Test-Output2 {
Write-Host "Hello World" -foreground Green
}
function Receive-Output {
process { Write-Host $_ -foreground Yellow }
}
#Output piped to another function, not displayed in first.
Test-Output | Receive-Output
#Output not piped to 2nd function, only displayed in first.
Test-Output2 | Receive-Output
#Pipeline sends to Out-Default at the end.
Test-Output
Вам потребуется заключить операцию конкатенации в круглые скобки, чтобы PowerShell обрабатывал конкатенацию перед токенизацией списка параметров для Write-Host
,
write-host ("count=" + $count)
Кстати, посмотрите это видео Джеффри Сновера, объясняющего, как работает конвейер. Когда я начал изучать PowerShell, я обнаружил, что это наиболее полезное объяснение того, как работает конвейер.
Помимо того, что упомянул Энди, есть еще одно отличие, которое может быть важным - запись-хост напрямую записывает на хост и ничего не возвращает, а это означает, что вы не можете перенаправить вывод, например, в файл.
---- script a.ps1 ----
write-host "hello"
Теперь запустите в PowerShell:
PS> .\a.ps1 > someFile.txt
hello
PS> type someFile.txt
PS>
Как видно, вы не можете перенаправить их в файл. Это может быть удивительно для тех, кто не осторожен.
Но если вместо этого использовать запись-вывод, перенаправление будет работать так, как ожидается.
Вот еще один способ сделать эквивалент записи-вывода. Просто поместите вашу строку в кавычки:
"count=$count"
Вы можете убедиться, что это работает так же, как Write-Output, запустив этот эксперимент:
"blah blah" > out.txt
Write-Output "blah blah" > out.txt
Write-Host "blah blah" > out.txt
Первые два будут выводить "бла-бла" в out.txt, а третье - нет.
"help Write-Output" дает подсказку о таком поведении:
Этот командлет обычно используется в сценариях для отображения строк и других объектов на консоли. Однако из-за поведения по умолчанию отображение объектов в конце конвейера обычно не требует использования командлета.
В этом случае сама строка "count=$count" является объектом в конце конвейера и отображается.
Для использования Write-Host
, PSScriptAnalyzer
производит следующую диагностику:
Избегать использования
Write-Host
поскольку он может работать не на всех хостах, не работает при отсутствии хоста и (до PS 5.0) не может быть подавлен, перехвачен или перенаправлен. Вместо этого используйтеWrite-Output
,Write-Verbose
, или жеWrite-Information
,
См. Документацию за этим правилом для получения дополнительной информации. Выдержки для потомков:
Использование
Write-Host
очень не рекомендуется, если в использовании команд сShow
глагол.Show
Глагол явно означает "показать на экране, без других возможностей".Команды с
Show
Глагол не имеет этой проверки.
У Джеффри Сновера есть запись в блоге Write-Host считается вредной, в которой он утверждает, что Write-Host - почти всегда неправильная вещь, потому что она мешает автоматизации и дает больше объяснений по поводу диагностики, однако вышеизложенное - хорошее резюме.
Из моего тестирования Write-Output и [Console]::WriteLine() работают намного лучше, чем Write-Host.
В зависимости от того, сколько текста вам нужно написать, это может быть важно.
Ниже приведен результат 5 тестов для каждого для Write-Host, Write-Output и [Console]::WriteLine().
Из своего ограниченного опыта я обнаружил, что при работе с любыми данными из реального мира мне нужно отказаться от командлетов и перейти к командам более низкого уровня, чтобы добиться какой-либо достойной производительности из моих сценариев.
measure-command {$count = 0; while ($count -lt 1000) { Write-Host "hello"; $count++ }}
1312ms
1651ms
1909ms
1685ms
1788ms
measure-command { $count = 0; while ($count -lt 1000) { Write-Output "hello"; $count++ }}
97ms
105ms
94ms
105ms
98ms
measure-command { $count = 0; while ($count -lt 1000) { [console]::WriteLine("hello"); $count++ }}
158ms
105ms
124ms
99ms
95ms
Относительно [Console]::WriteLine() - вы должны использовать его, если вы собираетесь использовать конвейеры в CMD (не в powershell). Скажем, вы хотите, чтобы ваш ps1 передавал много данных на стандартный вывод, а некоторые другие утилиты использовали их для преобразования / преобразования. Если вы используете Write-Host в скрипте, это будет намного медленнее.
write-host $("count=" + $count)
ИЛИ
write-host "count = $count"