Как вывести текст без новой строки в PowerShell?

Я хочу, чтобы мой PowerShell script напечатал что-то вроде этого:

Enabling feature XYZ......Done

script выглядит примерно так:

Write-Output "Enabling feature XYZ......."
Enable-SPFeature...
Write-Output "Done"

Но Write-Output всегда печатает новую строку в конце, поэтому мой вывод не находится в одной строке. Есть ли способ сделать это?

Ответ 1

Write-Host -NoNewline "Включение функции XYZ......." 

Ответ 2

К сожалению, как отмечено в нескольких ответах и ​​комментариях, Write-Host может быть опасным и не может быть передан в другие процессы, а Write-Output не имеет флага -NoNewline.

Но эти методы - это "* nix" способы отображения прогрессии, способ "PowerShell" для этого выглядит как Write-Progress: он отображает панель в верхней части окна PowerShell с информацией о ходе работы, доступной из PowerShell 3.0, см. Руководство для деталей.

# Total time to sleep
$start_sleep = 120

# Time to sleep between each notification
$sleep_iteration = 30

Write-Output ( "Sleeping {0} seconds ... " -f ($start_sleep) )
for ($i=1 ; $i -le ([int]$start_sleep/$sleep_iteration) ; $i++) {
    Start-Sleep -Seconds $sleep_iteration
    Write-Progress -CurrentOperation ("Sleep {0}s" -f ($start_sleep)) ( " {0}s ..." -f ($i*$sleep_iteration) )
}
Write-Progress -CurrentOperation ("Sleep {0}s" -f ($start_sleep)) -Completed "Done waiting for X to finish"

И взять пример OP:

# For the file log
Write-Output "Enabling feature XYZ"

# For the operator
Write-Progress -CurrentOperation "EnablingFeatureXYZ" ( "Enabling feature XYZ ... " )

Enable-SPFeature...

# For the operator
Write-Progress -CurrentOperation "EnablingFeatureXYZ" ( "Enabling feature XYZ ... Done" )

# For the log file
Write-Output "Feature XYZ enabled"

Ответ 3

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

Игнорируя, конечно, что этот пример глуп в вашем случае, но полезен по понятию:

$output = "Enabling feature XYZ......."
Enable-SPFeature...
$output += "Done"
Write-Output $output

Отображает:

Enabling feature XYZ.......Done

Ответ 4

Для записи в файл вы можете использовать массив байтов. В следующем примере создается пустой ZIP файл, который вы можете добавить в файл:

[Byte[]] $zipHeader = 80, 75, 5, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
[System.IO.File]::WriteAllBytes("C:\My.zip", $zipHeader)

Или используйте:

[Byte[]] $text = [System.Text.Encoding]::UTF8.getBytes("Enabling feature XYZ.......")
[System.IO.File]::WriteAllBytes("C:\My.zip", $text)

Ответ 5

Проблема, с которой я столкнулась, заключалась в том, что Write-Output фактически выводит строки на выходе при использовании PowerShell v2, по крайней мере, в stdout. Я пытался написать XML-текст в stdout без успеха, потому что это было бы сложно обернуть символом 80.

Обходной путь состоял в том, чтобы использовать

[Console]::Out.Write($myVeryLongXMLTextBlobLine)

Это не проблема в PowerShell v3. Кажется, что сработала запись-вывод.

В зависимости от того, как вызывается PowerShell script, вам может потребоваться использовать

[Console]::BufferWidth =< length of string, e.g. 10000)

прежде чем писать в стандартный вывод.

Ответ 6

В PowerShell, похоже, нет способа сделать это. Все предыдущие ответы неверны, потому что они не ведут себя так, как ведет себя Write-Output, но больше похоже на Write-Host, который в любом случае не имеет этой проблемы.

Закрывающее решение, похоже, использует Write-Host с параметром -NoNewLine. Вы не можете передать это, что является проблемой в целом, но есть способ переопределить эту функцию, как описано в Write-Host = > Экспортировать в файл, чтобы вы могли легко принять параметр для выходного файла. Это еще далеко не хорошее решение. С Start-Transcript это более удобно, но этот командлет имеет проблемы с собственными приложениями.

Write-Output просто не может делать то, что вам нужно в общем контексте.

Ответ 7

Да, поскольку другие ответы имеют состояния, это не может быть сделано с помощью Write-Output. В случае сбоя PowerShell, перейдите к .NET, есть даже несколько ответов .NET, но они сложнее, чем они должны быть.

Просто используйте:

[Console]::Write("Enabling feature XYZ.......")
Enable-SPFeature...
Write-Output "Done"

Это не самая чистая PowerShell, но она работает.

Ответ 8

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

Write-Output "Enabling feature XYZ" | Out-File "log.txt" # Pipe to log file Write-Host -NoNewLine "Enabling feature XYZ......." $result = Enable-SPFeature $result | Out-File "log.txt" # You could try{}catch{} an exception on Enable-SPFeature depending on what it doing if ($result -ne $null) { Write-Host "complete" } else { Write-Host "failed" }

Ответ 9

Вы просто не можете заставить PowerShell опустить эти надоедливые символы перевода строки... Нет script или командлета. Конечно, Write-Host - абсолютная глупость, потому что вы не можете перенаправлять/трубить с нее!

Тем не менее, вы можете написать свой собственный EXE файл, чтобы сделать это, что я объяснил, как это сделать в вопросе Как вывести что-то в PowerShell.

Ответ 10

Упрощение ответа FrinkTheBrave:

[System.IO.File]::WriteAllText("c:\temp\myFile.txt", $myContent)

Ответ 11

Ответ shufler правильный. Иными словами: вместо передачи значений в Write-Output с использованием ФОРМЫ МАШИН,

Write-Output "Parameters are:" $Year $Month $Day

или эквивалент несколькими вызовами Write-Output,

Write-Output "Parameters are:"
Write-Output $Year
Write-Output $Month
Write-Output $Day
Write-Output "Done."

сначала соедините ваши компоненты с STRING VARIABLE:

$msg="Parameters are: $Year $Month $Day"
Write-Output $msg

Это предотвратит промежуточные CRLF, вызванные вызовом Write-Output несколько раз (или ARRAY FORM), но, конечно, не будет подавлять окончательный CRLF в командном файле Write-Output. Для этого вам нужно будет написать свой собственный комманд, использовать один из других запутанных обходных решений, перечисленных здесь, или дождаться, пока Microsoft решит поддержать параметр -NoNewline для Write-Output.

Ваше желание предоставить текстовый индикатор прогресса на консоль (т.е. "...." ) в отличие от записи в файл журнала также должно быть удовлетворено с помощью Write-Host. Вы можете выполнить оба, собирая текст msg в переменную для записи в журнал AND, используя Write-Host, чтобы обеспечить прогресс в консоли. Эта функциональность может быть объединена в ваш собственный командный файл для лучшего повторного использования кода.

Ответ 12

Следующее поместит курсор назад в начале предыдущей строки. Вам нужно разместить его в правильном горизонтальном положении (используя $pos.X, чтобы переместить его в сторону):

$pos = $host.ui.RawUI.get_cursorPosition()
$pos.Y -= 1
$host.UI.RawUI.set_cursorPosition($Pos)

Ваш текущий выход составляет 27 пробелов, поэтому $pos.X = 27 может работать.

Ответ 13

Это может быть не очень элегантно, но это точно то, что запросил OP. Обратите внимание, что ISE работает с StdOut, поэтому выход не будет. Чтобы увидеть эту работу script, она не может быть запущена в ISE.

$stdout=[System.Console]::OpenStandardOutput()
$strOutput="Enabling feature XYZ... "
$stdout.Write(([System.Text.Encoding]::ASCII.GetBytes($strOutput)),0,$strOutput.Length)
Enable-SPFeature...
$strOutput="Done"
$stdout.Write(([System.Text.Encoding]::ASCII.GetBytes($strOutput)),0,$strOutput.Length)
$stdout.Close()

Ответ 14

Я обманул, но я считаю, что это единственный ответ, который отвечает всем требованиям. А именно, это позволяет избежать конечного CRLF, предоставляет место для выполнения другой операции за это время и надлежащим образом перенаправляет на стандартный вывод при необходимости.

$c_sharp_source = @"
using System;
namespace StackOverflow
{
   public class ConsoleOut
   {
      public static void Main(string[] args)
      {
         Console.Write(args[0]);
      }
   }
}
"@
$compiler_parameters = New-Object System.CodeDom.Compiler.CompilerParameters
$compiler_parameters.GenerateExecutable = $true
$compiler_parameters.OutputAssembly = "consoleout.exe"
Add-Type -TypeDefinition $c_sharp_source -Language CSharp -CompilerParameters $compiler_parameters

.\consoleout.exe "Enabling feature XYZ......."
Write-Output 'Done.'

Ответ 15

Вы можете это сделать абсолютно. Write-Output имеет флаг под названием " NoEnumerate", который по сути является тем же самым.