PowerShell'de yeni satır olmadan nasıl metin çıktısı alabilirim?


146

PowerShell betiğimin böyle bir şey yazdırmasını istiyorum:

Enabling feature XYZ......Done

Komut dosyası şöyle görünür:

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

Ama Write-Outputher zaman sonunda yeni bir satır yazdırır, böylece çıktım tek bir satırda olmaz. Bunu yapmanın bir yolu var mı?


Yanıtlar:


164

Write-Host -NoNewline "XYZ özelliğini etkinleştirme ......."


63
OP'nin örneği özellikle kullandığı için Write-Outputişlevinden çok farklı bir işleve sahip olduğu için indirildi Write-Host. Okuyucular, cevabı kopyalamadan / yapıştırmadan önce bu büyük tutarsızlığa dikkat etmelidir.
NathanAldenSr

5
@NathanAldenSr ile hemfikirim, bir dosyaya vb. Çıktı vermeye çalışıyorsanız Write-Host yardımcı olmuyor
stevethethread

6
Write-Hostneredeyse hiçbir zaman doğru cevap değildir. >/dev/ttyUnixland'da yapmaya eşdeğerdir.
Mark Reed

2
Write-Progressbazı durumlarda uygun olabilir, aşağıdaki örneğe bakın.
Thomas

12
OP örneği özellikle kullandığı için indirildi Write-Output. parametresine Write-Outputsahip değil -NoNewLine.
Slogmeister Extraordinaire

49

Ne yazık ki, gibi birçok cevaplar ve açıklamalarda belirtildiği Write-Hosttehlikeli olabilir ve diğer işlemlere borulu edilemez ve Write-Outputyok -NoNewlinebayrağı.

Ama bu yöntemler ekran ilerlemesi için "* Nix" yollardır, bunu yapmak için "PowerShell" yolu gibi görünüyor Write-Progress, bu ileriye PowerShell 3.0 edinilebilir ilerleme bilgi PowerShell penceresinin üst kısmında bir bar, görüntüler: manuel bakınız için detaylar.

# 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'nin örneğini ele almak için:

# 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
Bence bu durumu göstermek için en iyi çözüm. Eğer bir kütük ya da bir şeye ihtiyacınız varsa, Yazma-Çıktı satır çizgisiyle yaşamak zorundasınız.
fadanner

1
Kabul etti, artı aşamalı ekran noktası sadece canlı yükleme için "süslü olmak", günlük dosyalarına sahip olmanın bir anlamı yok: "bir şey yapmaya başla" sonra "bir şey yapmayı" yazdır
Thomas

13

Sizin durumunuzda çalışmayabilir (kullanıcıya bilgilendirici çıktı sağladığınızdan), çıktı eklemek için kullanabileceğiniz bir dize oluşturun. Çıktı alma zamanı geldiğinde, dizeyi çıktılamanız yeterlidir.

Elbette bu örneğin sizin durumunuzda aptalca olduğunu, ancak kavramda yararlı olduğunu görmezden gelmek:

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

ekranlar:

Enabling feature XYZ.......Done

1
Bu, sağlanan spesifik örnekte işe yarayabilir, ancak yine de tarafından üretilen fazladan bir satır beslemesi vardır Write-Output. Makul bir çözüm, ancak bir çözüm değil.
Slogmeister Extraordinaire

Write-Output her zaman sonunda bir satırsonu çıkarır. Bu cmdlet ile bunun hiçbir yolu yok
shufler

7
Özellik yüklendikten sonra tüm çıktı göründüğünden bu nokta değildir.
majkinetor

10
Anlamadım, kim bu soruya 1'den fazla upwote verir, çünkü özellik yüklendikten SONRA tüm çıkış göründüğü için bu nokta değil
maxkoryukov

1
"Tabii ki bu örnek sizin durumunuzda aptal ama konseptte yararlı olduğunu görmezden:"
shufler

6

Evet, diğer cevapların durumları olduğu gibi, Yazma-Çıktı ile yapılamaz. PowerShell başarısız olduğunda, .NET'e dönün, burada birkaç .NET yanıtı bile var, ancak olması gerekenden daha karmaşık.

Sadece kullan:

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

En saf PowerShell değil, işe yarıyor.


5
Aşağıdakiler seçildi, çünkü bu Write-Hostinsanlar gibi davranmıyor , ancak insanlar bunu beklemeyecek.
JBert

4

Bir dosyaya yazmak için bir bayt dizisi kullanabilirsiniz. Aşağıdaki örnek, dosya ekleyebileceğiniz boş bir ZIP dosyası oluşturur:

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

Veya kullan:

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

Bu harika bir örnek!
Peter Mortensen

2

FrinkTheBrave'nin cevabına basitleştirme:

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

Bu soruya hiç cevap vermiyor.
NathanAldenSr

2
Ama tam olarak aradığım şey ve sorunun başlığından beklediğim şey bu.
Patrick Roocks

2

Vurduğum sorun, en azından stdout için PowerShell v2'yi kullanırken Yazma-Çıktısının aslında çıktıyı satır kırmasıydı. Ben karakter 80 zor sarılmış olurdu çünkü başarılı olmadan stdout için bir XML metin yazmaya çalışıyordu.

Geçici çözüm,

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

Bu PowerShell v3'te bir sorun değildi. Write-Output orada düzgün çalışıyor gibi görünüyor.

PowerShell betiğinin nasıl çağrıldığına bağlı olarak,

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

stdout'a yazmadan önce.


2
Write-Host gibi davranır, ancak en kötüsü. Örneğin, dosyaya yönlendiremezsiniz.
majkinetor

2

PowerShell'de bunu yapmanın bir yolu yok gibi görünüyor. Önceki yanıtların hepsi doğru değildir, çünkü davranış biçiminde Write-Outputdavranmazlar, ancak daha Write-Hostçok bu problemi yaşamıyorlar.

Kapanış çözümü parametre Write-Hostile kullanılıyor gibi görünüyor -NoNewLine. Genel olarak bir sorun olan bu işlemi yapamazsınız, ancak bu işlevi Write-Host => Bir dosyaya aktar bölümünde açıklandığı gibi geçersiz kılmanın bir yolu vardır , böylece bir çıktı dosyası için parametreyi kolayca kabul etmesini sağlayabilirsiniz. Bu hala iyi bir çözümden uzak. Bununla Start-Transcriptdaha kullanışlı, ancak cmdlet'in yerel uygulamalarla ilgili sorunları var.

Write-Outputgenel bir bağlamda ihtiyacınız olanı yapamazsınız.


2

Write-Hostkorkunç, dünyaların bir muhriptir, ancak bunu Write-Outputgünlüğe kaydetmek için kullanırken bir kullanıcıya ilerleme göstermek için kullanabilirsiniz (OP'nin günlüğe kaydetmesini istemediğini değil).

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

İlerlemeyi gösterme gereksinimlerinize bağlı olarak, var Write-Progress.
chwarr

1

Bu sinir bozucu yeni satırları atlaması için PowerShell'i alamazsınız ... Bunu yapan bir komut dosyası veya cmdlet yoktur. Tabii ki, Write-Host mutlak saçmalıktır, çünkü yönlendiremezsiniz / ondan boru alamazsınız!

Yine de, bunu yapmak için kendi EXE dosyanızı yazabilirsiniz, bu nasıl Stack Overflow soru PowerShell bir şey çıktı nasıl açıklanır .


2
Yanlış bilgi. Shay ve Jay mükemmel bir şekilde cevaplarken, ilk argüman olarak -NoNewline'ı ekleyin.
David HotspotOffice'de

2
Belki de şimdi bu durumda @DavidatHotspotOffice, ancak en son işe yaramayan bir pencere kutusuna (bir yıl önce) dokunduğumda, Write-Host'dan yönlendirme / borulama yapamadınız. Adil olmak gerekirse, POSH veya .NET için en ufak bir sabrım yoktu, birkaç ay sonra bıraktım ve unix topraklarına geri döndüm. komik
samthebest

3
@DavidatHotspotOffice - Aslında haklı. Orijinal sorunun sorduğu Yazma-Çıktı için "NoNewLine" argümanı yoktur. Yazma Çıktısını kullanmak için bazı iyi nedenler var - bu cevap mantıklı. jsnover.com/blog/2013/12/07/write-host-considered-harmful
James Ruskin

Soru "PowerShell'de" bir çözüm istediğinden aşağı indirildi. Harici bir EXE yazmak "In PowerShell" değildir.
Slogmeister Extraordinaire

1
@SlogmeisterExtraordinaire PowerShell'de mümkün değil, bu nedenle cevabım makul. Sadece vahşetin çünkü dünyanın en kötü işletim sistemine sahip dünyanın en kötü işletim sistemiyle çalışmak zorunda olduğun için çok üzgündün.
samthebest

1

Shufler'ın cevabı doğrudur. Başka bir deyişle: ARRAY FORM'u kullanarak değerleri Write-Output'a geçirmek yerine,

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

veya birden fazla Yazma-Çıktı çağrısı ile eşdeğer,

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

bileşenlerinizi önce STRING VARIABLE olarak birleştirin:

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

Bu, Write-Output'u (veya ARRAY FORM) birden çok kez çağırmanın neden olduğu ara CRLF'leri engelleyecektir, ancak elbette Write-Output komutunun son CRLF'sini bastırmayacaktır. Bunun için kendi komutunuzu yazmanız, burada listelenen diğer kıvrımlı geçici çözümlerden birini kullanmanız veya Microsoft'un-NoNewline Yazma-Çıktı seçeneğini .

Bir günlük dosyasına yazmak yerine konsola metinsel ilerleme ölçer sağlama isteğiniz (örn. "...."), Write-Host kullanılarak da karşılanmalıdır. Hem msg metnini günlüğe yazmak için bir değişkene toplayarak VE konsola ilerleme sağlamak için Write-Host'u kullanarak gerçekleştirebilirsiniz. Bu işlevsellik, en iyi kod yeniden kullanımı için kendi komut dosyanızda birleştirilebilir.


Bu cevabı diğerlerine tercih ederim. Nesnelerin özelliklerini çağırıyorsanız, bunları tırnak işaretleri içine alamazsınız, bu yüzden kullandım: Write-Output ($ msg = $ MyObject.property + "Eklemek istediğim bazı metinler" + $ Object.property)
Lewis

2
@Lewis Bir dize içine kesinlikle nesne özellikleri ekleyebilirsiniz! Herhangi bir değişkeni çevrelemek için $ () ifadesini kullanın, örneğin "$ ($ MyObject.Property) $ ($ Object.property) dahil etmek istediğim bazı metinler"
shufler

Bu sağlanan belirli örnekte işe yarayabilir, ancak yine de tarafından üretilen fazladan bir satır beslemesi vardır Write-Output, bunu göremezsiniz çünkü bu son yazılan şeydir. Makul bir çözüm, ancak bir çözüm değil. Sonuçta ortaya çıkan çıktıyı tüketen, son satırın üstesinden gelemeyen bir şey olabilir.
Slogmeister Extraordinaire

1
Doğru değil. Çözüm tek bir komutla yapılamaz.
majkinetor

Bu soruya değinmiyor. Günlük dosyası çıktısı, arızanın görülmesi ve izlenmesi için denenmek üzere olan işlemi göstermelidir. Birleştirme bunu başaramaz.
durette

0

Aşağıdaki, imleci önceki satırın başına geri getirecektir. Doğru yatay konuma yerleştirmek size kalmıştır (yana doğru hareket ettirmek için $ pos.X kullanarak):

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

Geçerli çıktınız 27 boşluk üzerindedir, bu nedenle $ pos.X = 27 işe yarayabilir.


Bunun dosya çıktısı ile ilgisi yoktur.
Slogmeister Extraordinaire

Ayrıca o kadar da kötü değil. Ayrıca yaparsanız doğru çıktıyı üretebilir $pos.X. Sorun, bir dosyaya bağlarsanız, iki ayrı satırın görünmesidir.
majkinetor

0

Çok zarif olmayabilir, ancak OP'nin istediği şeyi tam olarak yapar. İMKB'nin StdOut ile uğraştığını unutmayın, bu nedenle çıktı alınmayacaktır. Bu komut dosyasının çalışmasını görmek için İMKB'de çalıştırılamaz.

$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
Doğru değil. Eğer bunu bir dosyaya koyarsanız ve çıktısını verirseniz hiçbir şey görünmez.
majkinetor

Bir dosyaya yöneltme OP'nin istediği bir şey değildi. Ve evet, [System.Console]bir dosyaya yönlendirilemez.
Slogmeister Extraordinaire

0

Aldattım, ama her gereksinimi karşılayan tek cevap bu olduğuna inanıyorum. Yani, bu izleyen CRLF'yi önler, bu arada diğer işlemin tamamlanması için bir yer sağlar ve gerektiği şekilde stdout'a doğru yönlendirir.

$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

arzu edilen o / p: XYZ özelliğini etkinleştirme ...... Tamam

aşağıdaki komutu kullanabilirsiniz

$ a = "XYZ özelliğini etkinleştirme"

Yazma çıkışı "$ a ...... Bitti"

tırnak içine değişken ve deyim eklemeniz gerekir. Umarım bu yardımcı olur :)

Teşekkürler Techiegal


Nesneleri boru hattına koymak için Write-Output tercih edilir. Metin görüntüleme için Write-Host sık kullanılır ve daha yakın zamanda Bilgi akışına yazmak için Write-Information kullanılır.
logicaldiagram

0

Burada zaten çok fazla cevap var, kimse burada aşağı kaymayacak. Her neyse, sonunda yeni bir satır olmadan metin yazmak için bir çözüm de var:

Kodlama ile dosya çıktısı:

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

Konsol çıkışı:

  # 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

Bunu kesinlikle yapabilirsiniz. Write- Output'un aslında aynı şey olan " NoEnumerate " adlı bir bayrağı vardır .

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.