Как вывести что-то в PowerShell

211

Я запускаю сценарий PowerShell из командного файла. Сценарий извлекает веб-страницу и проверяет, является ли содержимое страницы строкой «ОК».

Сценарий PowerShell возвращает уровень ошибки пакетному сценарию.

Пакетный скрипт выполняется ScriptFTP , программой автоматизации FTP. Если возникает ошибка, я могу сделать так, чтобы ScriptFTP отправлял всю консольную информацию администратору по электронной почте.

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

Я новичок в PowerShell и не уверен, какую функцию вывода использовать для этого. Я вижу три:

  • Написать-Host
  • Write-Output
  • Write-Error

Что было бы правильным для записи в эквивалент Windows stdout?

Пекка
источник

Ответы:

198

Простой вывод чего-то - это PowerShell - вещь прекрасная и одна из ее сильных сторон. Например, общий Hello, World! Приложение сводится к одной строке:

"Hello, World!"

Он создает строковый объект, назначает вышеупомянутое значение и, будучи последним элементом в командном конвейере, вызывает .toString()метод и выводит результат STDOUT(по умолчанию). Вещь красоты.

Другие Write-*команды предназначены для вывода текста в связанные потоки и имеют свое место как таковое.

Goyuix
источник
9
Это не совсем то, что происходит. Это строковое буквальное выражение и единственное в его конвейере. Таким образом, это эквивалентно "Hello, World!" | Out-Host. Out-Hostс другой стороны, отправляет объекты на хост PowerShell для отображения, и его реализация зависит от хоста. Консольный хост отправляет их на стандартный дескриптор вывода (проходя Out-Defaultпо пути), действительно. Однако PowerShell ISE отображает их в своей области вывода, а другие хосты могут делать и другие вещи полностью.
Джои
5
Объекты также не преобразуются вслепую в строку, а проходят через форматировщик, который решает, что с ними делать. Вот почему вы видите Get-ChildItem, например, что выходные данные представлены в виде таблицы, а результаты со многими свойствами (например, WMI) установлены по умолчанию Format-List.
Джои
120

Я думаю, что в этом случае вам понадобится Write-Output .

Если у вас есть сценарий, как

Write-Output "test1";
Write-Host "test2";
"test3";

затем, если вы вызовете скрипт с перенаправленным выводом, что-то вроде yourscript.ps1 > out.txt, вы попадете test2на экран test1\ntest3\nв «out.txt».

Обратите внимание, что «test3» и строка «Запись-вывод» всегда будут добавлять новую строку к вашему тексту, и в PowerShell нет способа остановить это (то есть echo -nэто невозможно в PowerShell с собственными командами). Если вам нужна функциональность (довольно простая и простая в Bash ), echo -nпосмотрите ответ samthebest .

Если командный файл запускает команду PowerShell, он, скорее всего, захватит команду Write-Output. У меня были «долгие дискуссии» с системными администраторами о том, что следует записывать в консоль, а что нет. Теперь мы согласились с тем, что единственная информация, если сценарий успешно выполнен или умер, должна быть Write-Hostотредактирована, и все, что может понадобиться автору сценария, должно быть известно о выполнении (какие элементы были обновлены, какие поля были установлены и т. Д.) Записать-Вывести. Таким образом, когда вы отправляете скрипт системному администратору, он может легко runthescript.ps1 >someredirectedoutput.txtи на экране увидеть, все ли в порядке. Затем отправьте «someredirectedoutput.txt» разработчикам.

naivists
источник
9

Я думаю, что следующее - хорошая выставка Echo vs. Write-Host . Обратите внимание, как test () на самом деле возвращает массив целых чисел, а не единственное целое число, как можно легко поверить.

function test {
    Write-Host 123
    echo 456 # AKA 'Write-Output'
    return 789
}

$x = test

Write-Host "x of type '$($x.GetType().name)' = $x"

Write-Host "`$x[0] = $($x[0])"
Write-Host "`$x[1] = $($x[1])"

Терминал выхода из вышеупомянутого:

123
x of type 'Object[]' = 456 789
$x[0] = 456
$x[1] = 789
user2426679
источник
Я могу смотреть на это весь день ... Но почему $x = testтолько печать, 123а не тоже 456?
not2qubit
7

Вы можете использовать любой из них в своем сценарии, так как они записывают в потоки по умолчанию (выходные данные и ошибки). Если бы вы передавали выходные данные в другой командлет, вы бы хотели использовать Write-Output , который в конечном итоге завершится в Write-Host .

В этой статье описываются различные параметры вывода: PowerShell O предназначен для вывода.

GrayWizardx
источник
1
Спасибо за ссылку. Боже, это сложно . Если Write-host - это какая-то конечная точка или функция очистки, я постараюсь пойти на это и доложить.
Пекка
3
Write-Host "Found file - " + $File.FullName -ForegroundColor Magenta

Пурпурный может быть одним из значений перечислителя "System.ConsoleColor" - Черный, Темно-синий, Темно-зеленый, Темно-коричневый, Темно-красный, Темно-пурпурный, Темно-желтый, Серый, Темно-серый, Синий, Зеленый, Голубой, Красный, Пурпурный, Желтый, Белый.

+ $File.FullNameНе является обязательным, и показывает , как поместить переменную в строку.

Иордания
источник
2

Вы просто не можете заставить PowerShell пропустить эти надоедливые переводы строк. Нет сценария или командлета, который делает это.

Конечно, Write-Host - абсолютная ерунда, потому что вы не можете перенаправлять / транслировать с нее! Вы просто должны написать свой собственный:

using System;

namespace WriteToStdout
{
    class Program
    {
        static void Main(string[] args)
        {
            if (args != null)
            {
                Console.Write(string.Join(" ", args));
            }
        }
    }
}

Например

PS C:\> writetostdout finally I can write to stdout like echo -n
finally I can write to stdout like echo -nPS C:\>
samthebest
источник
Вы можете сделать это в самой PowerShell. [System.Console] :: Write ("stringy") Однако вы не сможете вообще перенаправить его в powershell.
Николи
1
Что вы можете. Посмотрите этот вопрос
Слогмейстер Extraordinaire
1

Что было бы правильно использовать для записи в Windows эквивалент stdout?

В действительности , но очень к сожалению , как Windows PowerShell, так и PowerShell Core начиная с версии 7.0, все их 6 (!) Потоков вывода отправляются на стандартный вывод при вызове извне через интерфейс командной строки PowerShell .

  • Посмотрите эту проблему GitHub для обсуждения этого проблемного поведения, которое, вероятно, не будет исправлено ради обратной совместимости.

  • На практике это означает, что любой поток PowerShell, в который вы отправляете вывод, будет воспринят внешним вызывающим как вывод stdout :

    • Например, если вы выполните следующую cmd.exe, вы не будете видеть не выход, так как стандартный вывод перенаправление в NULравной степени относится ко всем PowerShell потоки:

      • C:\>powershell -noprofile -command "Write-Error error!" >NUL
    • Однако - любопытно - если вы перенаправить поток ошибок , PowerShell делает отправить свой поток ошибок в поток ошибок , так что с 2>вы можете перехватывать вывод ошибок потока выборочно; следующие выходные данные просто 'hi'- вывод потока успеха - при захвате вывода потока ошибок в файл err.txt:

      • C:\>powershell -noprofile -command "'hi'; Write-Error error!" 2>err.txt

Желательно поведением является:

  • Отправьте поток вывода успешных результатов1 PowerShell (число ) на стандартный вывод .
  • Отправлять вывод из всех других потоков в stderr , который является единственным вариантом, учитывая, что между процессами существует только 2 выходных потока: stdout (стандартный вывод) для данных и stderr (стандартная ошибка) для сообщений об ошибках и всех других типов сообщений - например, в качестве информации о состоянии - это не данные .

  • Желательно сделать это различие в вашем коде, даже если в настоящее время оно не соблюдается .


Внутри PowerShell :

  • Write-Hostэто для отображения вывода , и обходит выходной поток успеха - как таковой, его выход не может быть ни (непосредственно) захвачены в переменнойни подавленони перенаправлены.

    • Его первоначальная цель состояла в том, чтобы просто создать обратную связь с пользователем и создать простые, основанные на консоли пользовательские интерфейсы (цветной вывод).

    • Из - за невозможности предварительного быть захвачены или перенаправлены, версия PowerShell 5 из Write-Hostво вновь введенного потока информации (число 6), так что с тех пор она является можно захватывать и перенаправлять Write-Hostвывод.

  • Write-Errorпредназначен для записи нескончаемых ошибок в поток ошибок (число2); концептуально поток ошибок является эквивалентом stderr.

  • Write-Outputпишет в поток [output] success (число1 , который концептуально эквивалентен stdout; это поток для записи данных (результатов).

    • Тем не менее, явное использование Write-Outputредко требуется из-за неявной функции вывода PowerShell :
      • Выходные данные любой команды или выражения, которые явно не захвачены, не подавлены или не перенаправлены, автоматически отправляются в поток успеха ; Например, Write-Output "Honey, I'm $HOME"и "Honey, I'm $HOME"эквивалентны, причем последний не только более кратким, но и быстрее.
mklement0
источник