ฉันจะส่งออกข้อความโดยไม่ขึ้นบรรทัดใหม่ใน PowerShell ได้อย่างไร


145

ฉันต้องการสคริปต์ PowerShell ของฉันเพื่อพิมพ์สิ่งนี้:

Enabling feature XYZ......Done

สคริปต์มีลักษณะดังนี้:

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

แต่Write-Outputพิมพ์บรรทัดใหม่เสมอในตอนท้ายเพื่อผลลัพธ์ของฉันไม่ได้อยู่ในบรรทัดเดียว มีวิธีทำเช่นนี้หรือไม่?


คำตอบ:


165

เขียนโฮสต์ -NoNewline "การเปิดใช้งานฟีเจอร์ XYZ ....... "


62
Downvoted เพราะตัวอย่างของ OP โดยเฉพาะใช้ซึ่งมีฟังก์ชั่นที่แตกต่างกันอย่างมากมายกว่าWrite-Output Write-Hostผู้อ่านควรสังเกตความแตกต่างที่ยิ่งใหญ่นี้ก่อนที่จะคัดลอก / วางคำตอบ
NathanAldenSr

5
ฉันเห็นด้วยกับ @NathanAldenSr, Write-Host ไม่ได้ช่วยถ้าคุณพยายามที่จะส่งออกไปยังไฟล์อื่น ๆ
stevethethread

6
Write-Hostแทบจะไม่เคยได้คำตอบที่ถูกต้องเลย มันเทียบเท่ากับการทำ>/dev/ttyใน Unixland
Mark Reed

2
Write-Progressอาจเหมาะสมในบางกรณีดูตัวอย่างด้านล่าง
โทมัส

12
Downvoted เพราะตัวอย่างของ OP Write-Outputโดยเฉพาะใช้ Write-Outputไม่มี-NoNewLineพารามิเตอร์
Slogmeister Extraordinaire

49

น่าเสียดายที่ตามที่ระบุไว้ในคำตอบและความคิดเห็นต่าง ๆWrite-Hostอาจเป็นอันตรายและไม่สามารถส่งไปยังกระบวนการอื่นและWrite-Outputไม่มีการ-NoNewlineตั้งค่าสถานะ

แต่วิธีการเหล่านั้นเป็นวิธี "* ระวัง" เพื่อแสดงความก้าวหน้าวิธี "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
ฉันคิดว่านี่เป็นทางออกที่ดีที่สุดในการแสดงสถานะ หากคุณจำเป็นต้องมีบันทึกหรือสิ่งที่คุณต้องมีชีวิตอยู่กับการเขียนบรรทัดของการเขียนออก
fadanner

1
เห็นด้วยบวกกับจุดของจอแสดงผลแบบก้าวหน้าเป็นเพียง "เป็นแฟนซี" สำหรับการติดตั้งสดไม่มีจุดในการมีในล็อกไฟล์: พิมพ์ "เริ่มทำอะไร" แล้ว "ทำอะไรทำ"
โทมัส

13

แม้ว่ามันอาจไม่ทำงานในกรณีของคุณ (เนื่องจากคุณให้ข้อมูลที่เป็นประโยชน์แก่ผู้ใช้) ให้สร้างสตริงที่คุณสามารถใช้ต่อท้ายเอาต์พุต เมื่อถึงเวลาที่จะออกมันก็แค่เอาท์พุทสตริง

ไม่สนใจว่าตัวอย่างนี้โง่ในกรณีของคุณ แต่มีประโยชน์ในแนวคิด:

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

แสดง:

Enabling feature XYZ.......Done

1
นี้อาจทำงานในตัวอย่างที่เฉพาะเจาะจงให้ Write-Outputแต่ยังคงมีสายพิเศษฟีดที่ผลิตโดย วิธีแก้ปัญหาที่เหมาะสม แต่ไม่ใช่วิธีแก้ปัญหา
Slogmeister Extraordinaire

Write-Output จะแสดงบรรทัดใหม่เสมอในตอนท้าย ไม่มีทางแก้ไขเกี่ยวกับสิ่งนี้ด้วย cmdlet นี้
shufler

7
นี่ไม่ใช่จุดตั้งแต่เอาต์พุตทั้งหมดปรากฏขึ้นหลังจากติดตั้งฟีเจอร์
majkinetor

10
ฉันไม่เข้าใจใครให้มากกว่า 1 upwote กับคำถามนี้เพราะนี่ไม่ใช่จุดตั้งแต่ผลลัพธ์ทั้งหมดปรากฏขึ้นหลังจากติดตั้งคุณลักษณะแล้ว
maxkoryukov

1
"ไม่สนใจว่าตัวอย่างนี้โง่ในกรณีของคุณ แต่มีประโยชน์ในแนวคิด:"
shufler

6

ใช่เช่นเดียวกับคำตอบอื่น ๆ ที่มีรัฐก็ไม่สามารถทำได้กับการเขียนออก ที่ PowerShell ล้มเหลวให้เปลี่ยนเป็น. NET มีคำตอบจาก. NET เพียงไม่กี่คำ แต่ที่นี่ซับซ้อนกว่าที่พวกเขาต้องการ

เพียงใช้:

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

ไม่ใช่ PowerShell ที่บริสุทธิ์ที่สุด แต่ใช้งานได้


5
ลงเพราะสิ่งนี้มีลักษณะเหมือนWrite-Hostยกเว้นผู้คนจะไม่คาดหวัง
JBert

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

2

ความเรียบง่ายในการตอบสนองของ FrinkTheBrave:

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

นี่ไม่ได้ตอบคำถามเลย
NathanAldenSr

2
แต่มันเป็นสิ่งที่ฉันค้นหาและสิ่งที่ฉันคาดหวังจากชื่อของคำถาม
Patrick Roocks

2

ปัญหาที่ฉันตีคือการเขียน - เอาท์พุทจริง linebreaks เอาท์พุทเมื่อใช้ PowerShell v2 อย่างน้อย stdout ฉันพยายามเขียนข้อความ XML เพื่อ stdout โดยไม่ประสบความสำเร็จเพราะมันจะถูกห่อหุ้มด้วยอักขระ 80

วิธีแก้ปัญหาคือการใช้

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

นี่ไม่ใช่ปัญหาใน PowerShell v3 ดูเหมือนว่าเอาต์พุตการเขียนจะทำงานอย่างถูกต้อง

คุณอาจจำเป็นต้องใช้สคริปต์ PowerShell

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

ก่อนที่คุณจะเขียนถึง stdout


2
ทำงานเหมือน Write-Host แต่แย่ที่สุด คุณไม่สามารถไพพ์ไปที่ไฟล์เช่น
majkinetor

2

ดูเหมือนจะไม่มีวิธีการดังกล่าวใน PowerShell คำตอบก่อนหน้านี้ทั้งหมดไม่ถูกต้องเพราะพวกเขาไม่ได้ทำงานในลักษณะที่Write-Outputทำงาน แต่อื่น ๆ เช่นWrite-Hostที่ไม่มีปัญหานี้อยู่แล้ว

ดูเหมือนว่าโซลูชันการปิดจะใช้Write-Hostกับ-NoNewLineพารามิเตอร์ คุณไม่สามารถไพพ์นี้ซึ่งเป็นปัญหาโดยทั่วไป แต่มีวิธีที่จะแทนที่ฟังก์ชั่นนี้ตามที่อธิบายไว้ในWrite-Host => ส่งออกไปยังไฟล์ดังนั้นคุณสามารถทำให้มันยอมรับพารามิเตอร์สำหรับไฟล์เอาต์พุตได้อย่างง่ายดาย นี่ยังห่างไกลจากทางออกที่ดี ด้วยStart-Transcriptสิ่งนี้สามารถใช้งานได้มากกว่า แต่ cmdlet นั้นมีปัญหากับแอปพลิเคชั่นดั้งเดิม

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 เพื่อละเว้นบรรทัดใหม่ที่น่ารำคาญเหล่านั้น ... ไม่มีสคริปต์หรือ cmdlet ที่ทำ แน่นอนว่าWrite-Hostนั้นไร้สาระสมบูรณ์เพราะคุณไม่สามารถเปลี่ยนเส้นทาง / ไพพ์จากมันได้!

แต่คุณสามารถเขียนไฟล์ EXE ของคุณเองที่จะทำมันซึ่งเป็นสิ่งที่ผมอธิบายวิธีการทำในคำถามกองมากเกินวิธีการบางสิ่งบางอย่างที่ส่งออกใน PowerShell


2
ข้อมูลไม่ถูกต้อง ตามที่ Shay และ Jay ตอบอย่างยอดเยี่ยมเพียงเพิ่ม -NoNewline เป็นอาร์กิวเมนต์แรก
David ที่ HotspotOffice

2
อาจเป็นกรณีนี้ในขณะนี้ @DavidatHotspotOffice แต่เมื่อฉันสัมผัสกล่องหน้าต่าง (เมื่อปีที่แล้ว) ที่ไม่ได้ผลคุณไม่สามารถเปลี่ยนเส้นทาง / ไพพ์จาก Write-Host ได้ เพื่อความเป็นธรรมฉันไม่มีความอดทนเพียงเล็กน้อยสำหรับ POSH หรือ. NET ฉันเลิกหลังจากไม่กี่เดือนและกลับไปที่ unix land ตลก
samthebest

3
@DavidatHotspotOffice - จริงๆแล้วเขาถูกต้อง ไม่มีอาร์กิวเมนต์ "NoNewLine" สำหรับ Write-Output ซึ่งเป็นคำถามเดิมที่ถาม มีเหตุผลที่ดีบางประการดูเหมือนว่าสำหรับการใช้ Write-Output - ดังนั้นคำตอบนี้สมเหตุสมผล jsnover.com/blog/2013/12/07/write-host-considered-harmful
James Ruskin

ลดลงเนื่องจากคำถามกำลังขอวิธีแก้ไข "ใน PowerShell" การเขียน EXE ภายนอกไม่ใช่ "In PowerShell"
Slogmeister Extraordinaire

1
@SlogmeisterExtraordinaire เป็นไปไม่ได้ใน PowerShell ดังนั้นคำตอบของฉันก็สมเหตุสมผล downvoting เพียงของคุณเพราะเศร้ามากที่คุณต้องทำงานกับระบบปฏิบัติการที่แย่ที่สุดในโลกซึ่งมีเปลือกที่แย่ที่สุดในโลก
samthebest

1

คำตอบโดย shufler ถูกต้อง ระบุอีกวิธีหนึ่ง: แทนที่จะส่งค่าไปยัง Write-Output โดยใช้ ARRAY FORM

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

หรือเทียบเท่าโดยการเรียกหลาย ๆ ครั้งเพื่อเขียนเอาต์พุต

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 สุดท้ายของ Commandlet-Output สำหรับสิ่งนั้นคุณจะต้องเขียน commandlet ของคุณเองใช้วิธีแก้ไขปัญหาที่ซับซ้อนอย่างใดอย่างหนึ่งที่ระบุไว้ที่นี่หรือรอจนกว่า Microsoft ตัดสินใจที่จะสนับสนุน-NoNewlineตัวเลือกสำหรับ Write-Output

ความปรารถนาของคุณในการจัดเตรียมเครื่องวัดความคืบหน้าทางข้อความให้กับคอนโซล (เช่น ".... ") ซึ่งตรงข้ามกับการเขียนไปยังไฟล์บันทึกควรพึงพอใจโดยใช้ Write-Host คุณสามารถบรรลุทั้งสองโดยรวบรวมข้อความ msg เป็นตัวแปรสำหรับการเขียนไปยังบันทึกและใช้เขียนโฮสต์เพื่อให้ความคืบหน้าไปยังคอนโซล ฟังก์ชั่นนี้สามารถรวมเข้ากับ commandlet ของคุณเองเพื่อนำรหัสที่ยิ่งใหญ่มาใช้ซ้ำ


ฉันชอบคำตอบนี้มากกว่าคนอื่น ๆ หากคุณกำลังเรียกคุณสมบัติของวัตถุคุณไม่สามารถใส่มันไว้ในเครื่องหมายอัญประกาศได้ดังนั้นฉันจึงใช้: Write-Output ($ msg = $ MyObject.property + "ข้อความที่ฉันต้องการรวม" + $ Object.property)
Lewis

2
@Lewis คุณสามารถรวมคุณสมบัติของวัตถุไว้ในสตริงได้! ใช้นิพจน์ $ () เพื่อล้อมตัวแปรใด ๆ เช่น "$ ($ MyObject.Property) บางข้อความที่ฉันต้องการรวม $ ($ Object.property)"
shufler

สิ่งนี้อาจทำงานได้ในตัวอย่างเฉพาะที่ให้ไว้ แต่ยังมีฟีดบรรทัดพิเศษที่ผลิตโดยWrite-Outputคุณไม่สามารถเห็นได้เพราะมันเป็นสิ่งสุดท้ายที่เขียน วิธีแก้ปัญหาที่เหมาะสม แต่ไม่ใช่วิธีแก้ปัญหา อาจมีบางสิ่งที่ใช้เอาต์พุตผลลัพธ์ที่ไม่สามารถจัดการกับการขึ้นบรรทัดใหม่
Slogmeister Extraordinaire

1
ไม่ถูกต้อง. การแก้ปัญหาไม่สามารถทำได้ด้วยคำสั่งเดียว
majkinetor

นี่ไม่ได้ตอบคำถาม เอาต์พุตไฟล์บันทึกควรแสดงการดำเนินการที่กำลังพยายามทำอยู่เพื่อให้สามารถมองเห็นและตรวจสอบความล้มเหลวได้ การต่อข้อมูลไม่สำเร็จ
durette

0

ต่อไปนี้จะวางเคอร์เซอร์กลับไปที่จุดเริ่มต้นของแถวก่อนหน้า มันขึ้นอยู่กับคุณที่จะวางไว้ในตำแหน่งแนวนอนที่เหมาะสม (ใช้ $ pos.X เพื่อเลื่อนไปด้านข้าง):

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

ผลลัพธ์ปัจจุบันของคุณคือ 27 ช่องว่างดังนั้น$ pos.X = 27อาจใช้ได้


สิ่งนี้ไม่เกี่ยวกับเอาต์พุตไฟล์
Slogmeister Extraordinaire

มันยังไม่เลว มันสามารถสร้างผลลัพธ์ที่ถูกต้องหากคุณทำเช่น$pos.Xนั้น ปัญหาคือว่าถ้าคุณไปป์กับไฟล์จะมีสองบรรทัดแยกกันปรากฏขึ้น
majkinetor

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

การไปยังไฟล์ไม่ใช่สิ่งที่ OP ร้องขอ และใช่[System.Console]ไม่สามารถเปลี่ยนเส้นทางไปยังไฟล์
Slogmeister Extraordinaire

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

o / p ที่ต้องการ: เปิดใช้งานฟีเจอร์ XYZ ...... เสร็จสิ้น

คุณสามารถใช้คำสั่งด้านล่าง

$ a = "การเปิดใช้งานฟีเจอร์ XYZ"

เขียนผลลัพธ์ "$ a ...... Done"

คุณต้องเพิ่มตัวแปรและคำสั่งในเครื่องหมายคำพูด หวังว่านี่จะเป็นประโยชน์ :)

ขอบคุณ Techiegal


การเขียน - ส่งออกเป็นที่ต้องการสำหรับนำวัตถุออกไปป์ไลน์ สำหรับการแสดงข้อความ Write-Host ใช้บ่อยและล่าสุด Write-Information จะใช้เพื่อเขียนไปยังสตรีมข้อมูล
logicaldiagram

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.