PowerShellで改行なしでテキストを出力するにはどうすればよいですか?


145

PowerShellスクリプトで次のように出力したいのですが。

Enabling feature XYZ......Done

スクリプトは次のようになります。

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

しかし、Write-Output常に最後に改行を出力するので、出力は1行になりません。これを行う方法はありますか?


回答:


165

Write-Host -NoNewline "XYZ機能の有効化......."


62
OPの例では具体的にを使用Write-Outputしているため、反対票が投じられましたWrite-Host。読者は、回答をコピーして貼り付ける前に、この大きな違いに注意してください。
NathanAldenSr 2015年

5
@NathanAldenSrに同意します。ファイルなどに出力しようとしている場合、Write-Hostは役に立ちません
stevethethread

6
Write-Hostほとんどの場合、正しい答えはありません。>/dev/ttyUnixland で行うのと同じです。
Mark Reed

2
Write-Progress以下の例を参照してください。
トーマス

12
OPの例では特にを使用してWrite-Outputいるため、反対票が投じられました。パラメータWrite-Outputはありません-NoNewLine
Slogmeister Extraordinaire、2016

49

残念ながら、いくつかの回答とコメントに記載されているように、Write-Host危険である可能性があり、他のプロセスにパイプすることができずWrite-Output-NoNewlineフラグがありません。

しかし、これらのメソッドは進行状況を表示する「* nix」の方法であり、それを行う「PowerShell」の方法Write-Progressは、PowerShell 3.0から利用可能な進行状況情報を含むPowerShellウィンドウの上部にバーを表示します。マニュアル参照してください。詳細。

# 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
これはステータスを表示するための最良のソリューションだと思います。ログや何かが必要な場合は、Write-Outputの改行で生活する必要があります。
ファダーナー2017年

1
合意された、プラスプログレッシブ表示のポイントは、ライブインストールするための「空想する」だけで、ログファイルにそれを持つにはポイントがありません:印刷は、「何かをやって起動」し、「何かをして行って」
トーマス・

13

あなたのケースでは機能しないかもしれませんが(ユーザーに有益な出力を提供しているため)、出力を追加するために使用できる文字列を作成します。出力するときは、文字列を出力するだけです。

もちろん、この例はあなたのケースではばかげていますが、概念的には便利です:

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

ディスプレイ:

Enabling feature XYZ.......Done

1
これは、提供された特定の例では機能する可能性がありますが、によって生成される余分な改行がまだありWrite-Outputます。合理的な回避策ですが、解決策ではありません。
Slogmeister Extraordinaire、2016

Write-Outputは常に最後に改行を出力します。このコマンドレットでは
回避策

7
機能のインストール後に出力全体が表示されるため、これは重要ではありません。
majkinetor 2016年

10
ので、私は、この質問への1以上upwoteを与える人、理解していない。これは、以降のポイントではありません機能がインストールされた後、全体の出力が表示されます
maxkoryukov

1
「もちろん、この例があなたの場合ばかげているが、概念的には有用であることを無視する:」
shufler

6

はい、他の回答には状態があるため、Write-Outputでそれを行うことはできません。PowerShellが失敗した場合は、.NETに切り替えます。ここには.NETの回答もいくつかありますが、必要以上に複雑です。

ただ使用する:

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

純粋なPowerShellではありませんが、動作します。


5
これはWrite-Host、人々が期待しないことを除いて、と同じように動作するため、反対投票されました。
JBert 2017年

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)

それは素晴らしい例です!
Peter Mortensen 2017年


2

私が遭遇した問題は、PowerShell v2を使用して、少なくともstdoutに対してWrite-Outputが実際に出力を改行することでした。文字80でハードラップされるため、XMLテキストをstdoutに書き込もうとして成功しませんでした。

回避策は使用することでした

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

これはPowerShell v3の問題ではありませんでした。そこでWrite-Outputが正しく動作しているようです。

PowerShellスクリプトの呼び出し方法によっては、使用する必要がある場合があります

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

stdoutに書き込む前。


2
Write-Hostのように動作しますが、最悪です。たとえば、ファイルにパイプすることはできません。
majkinetor 2016年

2

PowerShellでこれを行う方法はないようです。以前の答えはすべて正しくありません。なぜなら、それらは振る舞いを振る舞わないが、とにかくこの問題はないWrite-Outputような振る舞いをするからWrite-Hostです。

closesソリューションはWrite-Host-NoNewLineパラメーターで使用するようです。これは一般的に問題となるパイプではできませんが、Write-Host => Export to a fileで説明されているようにこの関数をオーバーライドする方法があるため、出力ファイルのパラメーターを簡単に受け入れることができます。これはまだ良い解決策には程遠いです。これをStart-Transcript使用するとより使いやすくなりますが、そのコマンドレットにはネイティブアプリケーションに問題があります。

Write-Output一般的な状況では、必要なことを単に実行できません。


2

Write-Hostひどい、世界の破壊者ですがWrite-Output、ログに使用しているときにユーザーに進行状況を表示するためだけに使用できます(OPがログを要求したのではありません)。

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's doing
if ($result -ne $null) {
    Write-Host "complete"
} else {
    Write-Host "failed"
}

進行状況を示す必要性に応じて、もありWrite-Progressます。
chwarr

1

PowerShellでこれらの厄介な改行を省略することはできません。スクリプトやコマンドレットはありません。もちろん、Write-Hostはリダイレクト/パイプできないため、まったくナンセンスです。

それでも、独自のEXEファイルを作成してそれを行うことができます。これは、Stack Overflowの質問PowerShellで何かを出力する方法で行う方法を説明したものです。


2
誤った情報。シェイとジェイが上手に答えたので、最初の引数として単に-NoNewlineを追加します。
DavidはHotspotOfficeで2013年

2
多分それは今@DavidatHotspotOfficeの場合ですが、私が最後にウィンドウボックスに触れたとき(1年以上前)それが機能しなかった場合、Write-Hostからリダイレクト/パイプできませんでした。公平を期すために、私はPOSHや.NETに少しでも忍耐力がなかったので、数か月後に辞めてUNIXの土地に戻りました。おかしい
samthebest

3
@DavidatHotspotOffice-実際、彼は正しいです。Write-Outputには "NoNewLine"引数はありません。これは、元の質問が求めていたものです。Write-Outputを使用する理由はいくつかあります。この答えは理にかなっています。jsnover.com/blog/2013/12/07/write-host-considered-harmful
James Ruskin

質問は「PowerShellで」の解決策を求めているため、反対票を投じました。外部EXEの作成は「PowerShell内」ではありません。
Slogmeister Extraordinaire、2016

1
@SlogmeisterExtraordinaire PowerShellでは不可能なので、私の答えは合理的です。世界が最悪のシェルを持つ世界で最悪のオペレーティングシステムを使用する必要があるほど悲しいので、あなたの正反対の投票。
samthebest 2016

1

shuflerの答えは正しいです。別の言い方をすると、ARRAY FORMを使用して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

これにより、Write-Outputを複数回(またはARRAY FORM)呼び出すことによって発生する中間CRLFが防止されますが、当然、Write-Outputコマンドレットの最後のCRLFは抑制されません。そのためには、独自のコマンドレットを作成するか、ここにリストされている他の複雑な回避策のいずれかを使用するか、Microsoftが-NoNewlineWrite-Outputのオプションをサポートすることを決定するまで待つ必要があります。

ログファイルに書き込むのではなく、テキストプログレスメーターをコンソールに提供するという要望(つまり、「....」)も、Write-Hostを使用して満たす必要があります。ログに書き込むためにmsgテキストを変数に収集することと、コンソールに進行状況を提供するためにWrite-Hostを使用することの両方を行うことができます。この機能を独自のコマンドレットに組み合わせて、コードを最大限に再利用できます。


私は他の人よりもこの答えを好みます。オブジェクトのプロパティを呼び出す場合は、それらを引用符で囲むことができないため、次のように使用しました:Write-Output($ msg = $ MyObject.property + "Some text I want to include" + $ Object.property)
Lewis

2
@ルイス確かに文字列内にオブジェクトのプロパティを含めることができます!$()式を使用して任意の変数を囲みます。たとえば、「$($ MyObject.Property)含めたいテキスト$($ Object.property)」
shufler

これは、提供された特定の例では機能する可能性がありますが、によって生成された余分なラインフィードがまだありWrite-Outputます。それが最後に書かれたものであるため、それを見ることができません。合理的な回避策ですが、解決策ではありません。末尾の改行を処理できない結果の出力を消費するものがある可能性があります。
Slogmeister Extraordinaire、2016

1
正しくありません。ソリューションは、単一のコマンドでは実行できません。
majkinetor 2016年

これは問題に対処していません。ログファイルの出力には、試行された操作が示されているため、障害を確認して追跡できます。連結はそれを達成しません。
デュレット

0

次は、カーソルを前の行の先頭に戻します。それを正しい水平位置に配置するのはあなた次第です($ pos.Xを使用して横に移動します):

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

現在の出力は27スペース上なので、$ pos.X = 27でうまくいくかもしれません。


これはファイル出力とは関係ありません。
Slogmeister Extraordinaire、2016

それも悪くない。また、正しい出力を生成できます$pos.X。問題は、ファイルにパイプすると、2つの別々の行が表示されることです。
majkinetor 2016年

0

それはひどくエレガントではないかもしれませんが、OPが要求したとおりに実行します。ISEはStdOutを混乱させるため、出力はありません。このスクリプトが機能することを確認するために、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()

1
正しくありません。それをファイルに入れてパイプで出力すると、何も表示されません。
majkinetor 2016年

ファイルへのパイピングは、OPが要求したものではありませんでした。そして、はい、[System.Console]ファイルにリダイレクトすることはできません。
Slogmeister Extraordinaire 2017

0

私はだまされましたが、これがすべての要件に対処する唯一の答えだと思います。つまり、これは後続のCRLFを回避し、その間に他の操作を完了するための場所を提供し、必要に応じてstdoutに適切にリダイレクトします。

$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.'

0
$host.UI.Write('Enabling feature XYZ.......')
Enable-SPFeature...
$host.UI.WriteLine('Done')

0

望ましいo / p:機能XYZを有効にする......完了

以下のコマンドを使用できます

$ a = "XYZ機能を有効にする"

書き込み出力 "$ a ......完了"

引用符の中に変数とステートメントを追加する必要があります。これがお役に立てば幸いです:)

おかげでTechiegal


オブジェクトをパイプラインに配置するには、Write-Outputが推奨されます。テキスト表示の場合、Write-Hostが頻繁に使用され、最近では情報ストリームへの書き込みにWrite-Informationが使用されています。
論理図

0

ここにはすでにたくさんの答えがあります。誰もここにスクロールダウンしません。とにかく、次のように、最後に改行なしでテキストを書くための解決策もあります:

エンコードされたファイル出力:

  # a simple one liner
  "Hello World, in one line" | Out-File -Append -Encoding ascii -NoNewline -FilePath my_file.txt;

  # this is a test to show how it works
  "Hello World".Split(" ") | % { "_ $_ _" | Out-File -Append -Encoding ascii -NoNewline -FilePath my_file.txt; }

コンソール出力:

  # a simple one liner
  "Hello World, in one line" | Write-Host -NoNewline;

  # this is a test to show how it works
  "Hello World".Split(" ") | % { "_ $_ _" | Write-Host -NoNewline; }

-3

あなたは絶対にこれを行うことができます。Write-Outputには、本質的に同じものである「NoEnumerate」と呼ばれるフラグがあります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.