Bagaimana cara menampilkan teks tanpa baris baru di PowerShell?

145

Saya ingin skrip PowerShell saya mencetak sesuatu seperti ini:

Enabling feature XYZ......Done

Scriptnya terlihat seperti ini:

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

Tetapi Write-Outputselalu mencetak baris baru di akhir sehingga output saya tidak pada satu baris. Apakah ada cara untuk melakukan ini?

Amit G
sumber
3
Kemungkinan duplikat Menghindari baris baru dalam penulisan-keluaran
Michael Freidgeim

Jawaban:

165

Host-Tulis -NoNewline "Mengaktifkan fitur XYZ ......."

Shay Levy
sumber
62
Diturunkan karena contoh OP secara khusus menggunakan Write-Output, yang memiliki fungsi yang jauh berbeda dari Write-Host. Pembaca harus mencatat perbedaan besar ini sebelum menyalin / menempelkan jawabannya.
NathanAldenSr
5
Saya setuju dengan @NathanAldenSr, Write-Host tidak membantu jika Anda mencoba menampilkan ke file dll.
stevethethread
6
Write-Hosthampir tidak pernah jawaban yang benar. Ini sama dengan melakukan >/dev/ttydi Unixland.
Mark Reed
2
Write-Progressmungkin sesuai dalam beberapa kasus, lihat contoh di bawah ini.
Thomas
12
Diturunkan karena contoh OP secara khusus digunakan Write-Output. Write-Outputtidak memiliki -NoNewLineparameter.
Slogmeister Extraordinaire
49

Sayangnya, sebagaimana dicatat dalam beberapa jawaban dan komentar, Write-Hostbisa berbahaya dan tidak dapat disalurkan ke proses lain dan Write-Outputtidak memiliki -NoNewlinebendera.

Tetapi metode-metode itu adalah cara "* nix" untuk menampilkan perkembangan, cara "PowerShell" untuk melakukannya Write-Progress: menampilkan sebuah bar di bagian atas jendela PowerShell dengan informasi kemajuan, tersedia dari PowerShell 3.0 dan seterusnya, lihat manual untuk detail.

# 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"

Dan untuk mengambil contoh 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"
Thomas
sumber
3
Saya pikir ini adalah solusi terbaik untuk menunjukkan status. Jika Anda perlu memiliki log atau sesuatu yang Anda harus hidup dengan linebreak dari Write-Output.
fadanner
1
Setuju, plus tampilan progresif hanya "menjadi mewah" untuk instalasi langsung, tidak ada gunanya memilikinya dalam file log: cetak "mulai melakukan sesuatu" kemudian "selesai melakukan sesuatu"
Thomas
13

Meskipun mungkin tidak berfungsi dalam kasus Anda (karena Anda memberikan output informatif kepada pengguna), buat string yang dapat Anda gunakan untuk menambahkan output. Ketika tiba saatnya untuk meng-output-nya, output saja string.

Tentu saja mengabaikan contoh ini konyol dalam kasus Anda tetapi berguna dalam konsep:

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

Menampilkan:

Enabling feature XYZ.......Done
Shufler
sumber
1
Ini dapat bekerja pada contoh spesifik yang diberikan, tetapi masih ada umpan garis tambahan yang dihasilkan oleh Write-Output. Solusi yang masuk akal, tetapi bukan solusi.
Slogmeister Extraordinaire
Write-Output selalu menampilkan baris baru di akhir. Tidak ada jalan lain dengan cmdlet ini
shufler
7
Ini bukan intinya karena seluruh output muncul setelah fitur diinstal.
majkinetor
10
Saya tidak mengerti, siapa yang memberikan lebih dari 1 upwote untuk pertanyaan ini, karena Ini bukan intinya karena seluruh output muncul SETELAH fitur diinstal
maxkoryukov
1
"Mengabaikan tentu saja bahwa contoh ini konyol dalam kasus Anda tetapi berguna dalam konsep:"
shufler
6

Ya, karena jawaban lain menyatakan, itu tidak dapat dilakukan dengan Write-Output. Di mana PowerShell gagal, buka .NET, bahkan ada beberapa jawaban .NET di sini tetapi lebih kompleks dari yang seharusnya.

Cukup gunakan:

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

Ini bukan PowerShell yang paling murni, tetapi bekerja.

Mark Travis
sumber
5
Diturunkan karena ini berperilaku seperti Write-Host, kecuali orang tidak akan mengharapkannya.
JBert
4

Untuk menulis ke file Anda dapat menggunakan array byte. Contoh berikut membuat file ZIP kosong, yang dapat Anda tambahkan file ke:

[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)

Atau gunakan:

[Byte[]] $text = [System.Text.Encoding]::UTF8.getBytes("Enabling feature XYZ.......")
[System.IO.File]::WriteAllBytes("C:\My.zip", $text)
FrinkTheBrave
sumber
Itu adalah contoh yang luar biasa!
Peter Mortensen
2

Penyederhanaan terhadap respons FrinkTheBrave:

[System.IO.File]::WriteAllText("c:\temp\myFile.txt", $myContent)
Russell Speight
sumber
Ini sama sekali tidak menjawab pertanyaan.
NathanAldenSr
2
Tetapi justru itulah yang saya cari dan apa yang saya harapkan dari judul pertanyaan.
Patrick Roocks
2

Masalah yang saya tekan adalah bahwa Write-Output sebenarnya linebreak output ketika menggunakan PowerShell v2, setidaknya untuk stdout. Saya mencoba untuk menulis teks XML ke stdout tanpa hasil, karena itu akan sulit terbungkus pada karakter 80.

Solusinya adalah menggunakan

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

Ini bukan masalah di PowerShell v3. Write-Output tampaknya berfungsi dengan baik di sana.

Bergantung pada bagaimana skrip PowerShell dipanggil, Anda mungkin perlu menggunakan

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

sebelum Anda menulis ke stdout.

eythort
sumber
2
Berperilaku seperti Write-Host, tetapi yang terburuk. Anda tidak dapat mengirim pipa ke file misalnya.
majkinetor
2

Sepertinya tidak ada cara untuk melakukan ini di PowerShell. Semua jawaban sebelumnya tidak benar, karena mereka tidak berperilaku seperti itu Write-Outputtetapi lebih seperti Write-Hostyang tidak memiliki masalah ini.

Solusi closes sepertinya digunakan Write-Hostdengan -NoNewLineparameter. Anda tidak dapat mem-pipe ini yang merupakan masalah secara umum, tetapi ada cara untuk menimpa fungsi ini seperti dijelaskan dalam Write-Host => Ekspor ke file , sehingga Anda dapat dengan mudah membuatnya menerima parameter untuk file output. Ini masih jauh dari solusi yang bagus. Dengan Start-Transcriptini lebih dapat digunakan, tetapi cmdlet itu memiliki masalah dengan aplikasi asli.

Write-Outputtidak bisa melakukan apa yang Anda butuhkan dalam konteks umum.

majkinetor
sumber
2

Write-Hostmengerikan, perusak dunia, namun Anda dapat menggunakannya hanya untuk menampilkan kemajuan kepada pengguna saat menggunakan Write-Outputuntuk log (bukan bahwa OP meminta penebangan).

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"
}
eodeluga
sumber
Tergantung pada kebutuhan Anda untuk menunjukkan kemajuan, ada juga Write-Progress.
chwarr
1

Anda tidak bisa mendapatkan PowerShell untuk menghilangkan baris baru yang sial itu ... Tidak ada skrip atau cmdlet yang melakukannya. Tentu saja, Write-Host adalah omong kosong mutlak, karena Anda tidak dapat mengarahkan / pipa darinya!

Namun demikian, Anda dapat menulis file EXE Anda sendiri untuk melakukannya, itulah yang saya jelaskan bagaimana melakukannya di Stack Overflow. Bagaimana cara mengeluarkan sesuatu di PowerShell .

samthebest
sumber
2
Informasi salah. Saat Shay dan Jay menjawab dengan sangat baik, cukup tambahkan -NoNewline sebagai argumen pertama.
David di HotspotOffice
2
Mungkin itu masalahnya sekarang @DavidatHotspotOffice tetapi ketika saya terakhir menyentuh kotak windows (lebih dari setahun yang lalu) yang tidak berfungsi, Anda tidak bisa mengarahkan / pipa dari Write-Host. Agar adil saya tidak memiliki sedikit pun kesabaran untuk POSH atau .NET, saya berhenti setelah beberapa bulan dan kembali ke tanah unix. funny
samthebest
3
@DavidatHotspotOffice - Sebenarnya, dia benar. Tidak ada argumen "NoNewLine" untuk Write-Output, yang merupakan pertanyaan awal. Ada beberapa alasan bagus untuk menggunakan Write-Output - jadi jawaban ini masuk akal. jsnover.com/blog/2013/12/07/write-host-considered-harmful
James Ruskin
Diturunkan karena pertanyaan meminta solusi "di PowerShell". Menulis EXE eksternal bukan "In PowerShell".
Slogmeister Extraordinaire
1
@ LogmeisterExtraordinaire Tidak dimungkinkan di PowerShell karena itu jawaban saya masuk akal. Anda hanya downvoting karena Anda sangat sedih bahwa Anda harus bekerja dengan sistem operasi terburuk di dunia yang memiliki shell terburuk di dunia.
samthebest
1

Jawaban oleh shufler benar. Dinyatakan dengan cara lain: Alih-alih meneruskan nilai ke Write-Output menggunakan FORMULIR ARRAY,

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

atau setara dengan beberapa panggilan ke Write-Output,

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

gabungkan komponen Anda menjadi STRING VARIABLE terlebih dahulu:

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

Ini akan mencegah CRLF perantara yang disebabkan oleh panggilan Write-Output beberapa kali (atau FORMULIR ARRAY), tetapi tentu saja tidak akan menekan CRLF akhir dari commandlet Output-Tulis. Untuk itu, Anda harus menulis commandlet Anda sendiri, menggunakan salah satu dari solusi yang berbelit-belit yang tercantum di sini, atau menunggu hingga Microsoft memutuskan untuk mendukung -NoNewlineopsi untuk Write-Output.

Keinginan Anda untuk memberikan pengukur kemajuan teks ke konsol (yaitu "....") yang bertentangan dengan penulisan ke file log, juga harus dipenuhi dengan menggunakan Write-Host. Anda dapat menyelesaikan keduanya dengan mengumpulkan teks pesan ke dalam variabel untuk ditulis ke log DAN menggunakan Write-Host untuk memberikan kemajuan ke konsol. Fungsi ini dapat digabungkan ke dalam commandlet Anda sendiri untuk penggunaan kembali kode terhebat.

David Rudd
sumber
Saya lebih suka jawaban ini daripada yang lain. Jika Anda memanggil properti objek, Anda tidak dapat menyertakannya dalam tanda kutip jadi saya menggunakan: Write-Output ($ msg = $ MyObject.property + "Beberapa teks yang ingin saya sertakan" + $ Object.property)
Lewis
2
@Lewis Anda tentu saja dapat memasukkan properti objek di dalam string! Gunakan ekspresi $ () untuk mengelilingi variabel apa pun, mis. "$ ($ MyObject.Property) Beberapa teks yang saya ingin sertakan $ ($ Object.property)"
shufler
Ini dapat bekerja pada contoh spesifik yang diberikan, tetapi masih ada umpan baris tambahan yang dihasilkan oleh Write-Output, Anda tidak dapat melihatnya karena ini adalah hal terakhir yang ditulis. Solusi yang masuk akal, tetapi bukan solusi. Mungkin ada sesuatu yang mengkonsumsi output yang dihasilkan yang tidak dapat menangani baris tambahan.
Slogmeister Extraordinaire
1
Tidak benar. Solusinya tidak bisa dilakukan dengan satu perintah.
majkinetor
Ini tidak menjawab pertanyaan. Keluaran file log harus menunjukkan operasi yang hendak dicoba sehingga kegagalan dapat dilihat dan dilacak. Penggabungan tidak mencapai itu.
Durette
0

Berikut ini akan menempatkan kursor kembali di awal baris sebelumnya. Terserah Anda untuk meletakkannya di posisi horizontal kanan (menggunakan $ pos.X untuk memindahkannya ke samping):

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

Output Anda saat ini adalah 27 spasi lebih, jadi $ pos.X = 27 mungkin berfungsi.

Will Martin
sumber
Ini tidak ada hubungannya dengan output file.
Slogmeister Extraordinaire
Ini juga tidak terlalu buruk. Ini dapat menghasilkan output yang benar jika Anda melakukannya $pos.Xjuga. Masalahnya adalah bahwa jika Anda memipangnya ke file, dua baris terpisah muncul.
majkinetor
0

Ini mungkin tidak terlalu elegan, tetapi ia melakukan persis seperti yang diminta OP. Perhatikan bahwa ISE mengacaukan StdOut, sehingga tidak akan ada output. Agar skrip ini berfungsi, skrip tidak dapat dijalankan dalam 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()
Slogmeister Luar Biasa
sumber
1
Tidak benar. Jika Anda meletakkannya di file dan pipa hasilnya tidak akan muncul.
majkinetor
Perpipaan ke file bukanlah sesuatu yang diminta OP. Dan ya, [System.Console]tidak dapat diarahkan ke file.
Slogmeister Extraordinaire
0

Saya curang, tetapi saya percaya ini adalah satu-satunya jawaban yang memenuhi setiap persyaratan. Yaitu, ini menghindari CRLF tertinggal, menyediakan tempat bagi operasi lain untuk menyelesaikan sementara, dan mengarahkan kembali ke stdout seperlunya.

$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.'
durette
sumber
0
$host.UI.Write('Enabling feature XYZ.......')
Enable-SPFeature...
$host.UI.WriteLine('Done')
BG100
sumber
0

o / p yang diinginkan: Mengaktifkan fitur XYZ ...... Selesai

Anda dapat menggunakan perintah di bawah ini

$ a = "Mengaktifkan fitur XYZ"

Tulis-output "$ a ...... Selesai"

Anda harus menambahkan variabel dan pernyataan di dalam tanda kutip. semoga ini membantu :)

Terima kasih Techiegal

techiegal
sumber
Write-Output lebih disukai untuk meletakkan objek ke pipa. Untuk tampilan teks, Write-Host sering digunakan dan baru-baru ini Write-Information digunakan untuk menulis ke aliran Informasi.
logicaldiagram
0

Sudah ada begitu banyak jawaban di sini, tidak ada yang akan gulir ke sini. Bagaimanapun juga ada solusi untuk menulis teks tanpa baris baru di akhir, dengan yang berikut:

Output file dengan penyandian:

  # 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; }

Output konsol:

  # 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; }
SchLx
sumber
-3

Anda benar-benar dapat melakukan ini. Write-Output memiliki bendera yang disebut " NoEnumerate " yang pada dasarnya adalah hal yang sama.

Bau
sumber