Làm cách nào để xuất văn bản mà không có dòng mới trong PowerShell?


145

Tôi muốn tập lệnh PowerShell của tôi in một cái gì đó như thế này:

Enabling feature XYZ......Done

Kịch bản trông giống như thế này:

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

Nhưng Write-Outputluôn luôn in một dòng mới ở cuối để đầu ra của tôi không nằm trên một dòng. Có cách nào để làm việc này không?


Câu trả lời:


165

Write-Host -NoNewline "Kích hoạt tính năng XYZ ......."


62
Bị từ chối vì ví dụ của OP sử dụng cụ thể Write-Output, có chức năng rất khác so với Write-Host. Độc giả nên lưu ý sự khác biệt lớn này trước khi sao chép / dán câu trả lời.
NathanAldenSr 7/03/2015

5
Tôi đồng ý với @NathanAldenSr, Write-Host không giúp ích gì nếu bạn đang cố xuất ra một tệp, v.v.
stevethethread

6
Write-Hostgần như không bao giờ là câu trả lời đúng Nó tương đương với việc làm >/dev/ttytrong Unixland.
Mark Reed

2
Write-Progresscó thể thích hợp trong một số trường hợp, xem ví dụ dưới đây.
Thomas

12
Bị từ chối vì ví dụ của OP sử dụng cụ thể Write-Output. Write-Outputkhông có -NoNewLinetham số.
Slogmeister Extraordinaire

49

Thật không may, như đã lưu ý trong một số câu trả lời và nhận xét, Write-Hostcó thể nguy hiểm và không thể được chuyển sang các quy trình khác và Write-Outputkhông có -NoNewlinecờ.

Nhưng các phương pháp đó là "* nix" cách để tiến hiển thị, các "PowerShell" cách để làm điều đó dường như là Write-Progress: nó sẽ hiển thị một thanh ở phía trên cùng của cửa sổ PowerShell với thông tin tiến bộ, có sẵn từ PowerShell 3.0 trở đi, xem hướng dẫn sử cho chi tiết.

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

Và lấy ví dụ của 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
Tôi nghĩ rằng đây là giải pháp tốt nhất để hiển thị trạng thái. Nếu bạn cần phải có một bản ghi hoặc một cái gì đó bạn phải sống với dòng đầu ra của Ghi-Xuất.
fadanner

1
Đồng ý, cộng với điểm hiển thị lũy tiến chỉ là "được ưa thích" để cài đặt trực tiếp, không có lý do gì để có nó trong các tệp nhật ký: in "bắt đầu làm gì đó" sau đó "thực hiện việc gì đó"
Thomas

13

Mặc dù nó có thể không hoạt động trong trường hợp của bạn (vì bạn đang cung cấp đầu ra thông tin cho người dùng), hãy tạo một chuỗi mà bạn có thể sử dụng để nối thêm đầu ra. Khi đến lúc xuất nó, chỉ cần xuất chuỗi.

Tất nhiên bỏ qua rằng ví dụ này là ngớ ngẩn trong trường hợp của bạn nhưng hữu ích trong khái niệm:

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

Hiển thị:

Enabling feature XYZ.......Done

1
Điều này có thể hoạt động trong ví dụ cụ thể được cung cấp, nhưng vẫn có một nguồn cấp dữ liệu bổ sung được sản xuất bởi Write-Output. Cách giải quyết hợp lý, nhưng không phải là một giải pháp.
Slogmeister Extraordinaire

Đầu ra ghi luôn xuất ra một dòng mới ở cuối. Không có cách nào khác với điều này với lệnh ghép ngắn này
shufler

7
Đây không phải là điểm vì toàn bộ đầu ra xuất hiện sau khi tính năng được cài đặt.
Majkinetor

10
Tôi không hiểu, người cung cấp nhiều hơn 1 câu hỏi cho câu hỏi này, bởi vì đây không phải là điểm vì toàn bộ đầu ra xuất hiện SAU tính năng được cài đặt
maxkoryukov

1
"Bỏ qua tất nhiên rằng ví dụ này là ngớ ngẩn trong trường hợp của bạn nhưng hữu ích trong khái niệm:"
shufler

6

Có, như các câu trả lời khác có trạng thái, không thể thực hiện được với Đầu ra ghi. Trường hợp PowerShell thất bại, hãy chuyển sang .NET, thậm chí có một vài câu trả lời .NET ở đây nhưng chúng phức tạp hơn mức cần thiết.

Chỉ dùng:

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

Nó không phải là PowerShell thuần túy nhất, nhưng nó hoạt động.


5
Bị hạ thấp bởi vì điều này hành xử giống như Write-Host, ngoại trừ mọi người sẽ không mong đợi nó.
JBert

4

Để ghi vào một tập tin, bạn có thể sử dụng một mảng byte. Ví dụ sau đây tạo một tệp ZIP trống, bạn có thể thêm tệp vào:

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

Hoặc dùng:

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

Đó là một ví dụ tuyệt vời!
Peter Mortensen

2

Đơn giản hóa cho phản hồi của FrinkTheBrave:

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

Điều này không trả lời câu hỏi nào cả.
NathanAldenSr 7/03/2015

2
Nhưng nó chính xác là những gì tôi đã tìm kiếm và những gì tôi mong đợi từ tiêu đề của câu hỏi.
Patrick Roocks 20/03/2015

2

Vấn đề mà tôi gặp phải là Write-Output thực sự phá vỡ đầu ra khi sử dụng PowerShell v2, ít nhất là cho thiết bị xuất chuẩn. Tôi đã cố gắng viết một văn bản XML thành thiết bị xuất chuẩn mà không thành công, bởi vì nó sẽ khó khăn trong ký tự 80.

Cách giải quyết là sử dụng

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

Đây không phải là một vấn đề trong PowerShell v3. Write-Output dường như đang hoạt động đúng ở đó.

Tùy thuộc vào cách tập lệnh PowerShell được gọi, bạn có thể cần sử dụng

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

trước khi bạn viết lên thiết bị xuất chuẩn.


2
Hành vi như Write-Host, nhưng tệ nhất. Bạn không thể đưa nó vào tập tin chẳng hạn.
Majkinetor

2

Dường như không có cách nào để làm điều này trong PowerShell. Tất cả các câu trả lời trước đó đều không đúng, vì chúng không hành xử theo cách Write-Outputcư xử mà giống như Write-Hostkhông có vấn đề gì.

Các giải pháp đóng dường như sử dụng Write-Hostvới -NoNewLinetham số. Nói chung, bạn không thể xử lý vấn đề này, nhưng có một cách để ghi đè chức năng này như được mô tả trong Write-Host => Xuất ra tệp , vì vậy bạn có thể dễ dàng chấp nhận tham số cho tệp đầu ra. Đây vẫn là một giải pháp tốt. Với Start-Transcriptđiều này có thể sử dụng nhiều hơn, nhưng cmdlet đó có vấn đề với các ứng dụng gốc.

Write-Outputchỉ đơn giản là không thể làm những gì bạn cần trong một bối cảnh chung.


2

Write-Hostlà khủng khiếp, một kẻ hủy diệt thế giới, nhưng bạn có thể sử dụng nó chỉ để hiển thị tiến trình cho người dùng trong khi sử dụng Write-Outputđể đăng nhập (không phải OP yêu cầu đăng nhập).

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

Tùy thuộc vào nhu cầu của bạn để chỉ ra sự tiến bộ, cũng có Write-Progress.
chwarr

1

Bạn chỉ đơn giản là không thể có được PowerShell để bỏ qua những dòng mới phiền phức đó ... Không có tập lệnh hay lệnh ghép ngắn nào. Tất nhiên, Write-Host hoàn toàn vô nghĩa, bởi vì bạn không thể chuyển hướng / đường ống từ nó!

Tuy nhiên, bạn có thể viết tệp EXE của riêng mình để thực hiện, đó là những gì tôi đã giải thích cách thực hiện trong câu hỏi Stack Overflow Cách xuất nội dung nào đó trong PowerShell .


2
Thông tin không chính xác. Như Shay và Jay đã trả lời một cách xuất sắc, chỉ cần thêm -NoNewline làm đối số đầu tiên.
David tại HotspotOffice

2
Có thể đó là trường hợp bây giờ @DavidatHotspotOffice nhưng khi tôi chạm vào một ô cửa sổ (hơn một năm trước) không hoạt động, bạn không thể chuyển hướng / đường ống từ Write-Host. Để công bằng, tôi đã không có một chút kiên nhẫn cho POSH hoặc .NET, tôi đã bỏ việc sau một vài tháng và quay trở lại đất liền. vui nhộn
samthebest

3
@DavidatHotspotOffice - Thật ra, anh ấy đúng. Không có đối số "NoNewLine" cho đầu ra ghi, đó là những gì câu hỏi ban đầu được hỏi về. Có một số lý do chính đáng, dường như, khi sử dụng Write-Output - vì vậy câu trả lời này có ý nghĩa. jsnover.com/blog/2013/12/07/write-host-considered-harmful
James Ruskin

Bị từ chối vì câu hỏi đang yêu cầu giải pháp "trong PowerShell". Viết EXE bên ngoài không phải là "Trong PowerShell".
Slogmeister Extraordinaire

1
@SlogmeisterExtraordinaire Không thể có trong PowerShell do đó câu trả lời của tôi là hợp lý. Bạn chỉ bị hạ thấp bởi vì bạn rất buồn khi bạn phải làm việc với hệ điều hành tồi tệ nhất thế giới có vỏ xấu nhất thế giới.
samthebest

1

Câu trả lời của shufler là chính xác. Nói cách khác: Thay vì chuyển các giá trị sang Đầu ra ghi bằng MẪU ARRAY,

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

hoặc tương đương bởi nhiều cuộc gọi đến Đầu ra ghi,

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

trước tiên hãy ghép các thành phần của bạn thành một BIẾN ĐỔI CHUINGI:

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

Điều này sẽ ngăn các CRLF trung gian gây ra bằng cách gọi Đầu ra ghi nhiều lần (hoặc MẪU ARRAY), nhưng tất nhiên sẽ không triệt tiêu CRLF cuối cùng của lệnh Lệnh đầu ra. Vì vậy, bạn sẽ phải viết lệnh của riêng mình, sử dụng một trong các cách giải quyết phức tạp khác được liệt kê ở đây hoặc đợi cho đến khi Microsoft quyết định hỗ trợ -NoNewlinetùy chọn cho Đầu ra ghi.

Mong muốn của bạn để cung cấp một máy đo tiến độ văn bản cho bảng điều khiển (tức là "....") thay vì ghi vào tệp nhật ký, cũng nên được thỏa mãn bằng cách sử dụng Máy chủ ghi. Bạn có thể thực hiện cả hai bằng cách thu thập văn bản thông điệp thành một biến để ghi vào nhật ký VÀ sử dụng Write-Host để cung cấp tiến trình cho bảng điều khiển. Chức năng này có thể được kết hợp vào tập lệnh của riêng bạn để tái sử dụng mã lớn nhất.


Tôi rất thích câu trả lời này hơn những người khác. Nếu bạn đang gọi các thuộc tính của các đối tượng, bạn không thể đặt chúng trong dấu ngoặc kép nên tôi đã sử dụng: Write-Output ($ dir = $ MyObject.property + "Một số văn bản tôi muốn đưa vào" + $ Object.property)
Lewis

2
@Lewis Bạn chắc chắn có thể bao gồm các thuộc tính đối tượng trong một chuỗi! Sử dụng biểu thức $ () để bao quanh bất kỳ biến nào, ví dụ: "$ ($ MyObject.Property) Một số văn bản tôi muốn bao gồm $ ($ Object.property)"
shufler

Điều này có thể hoạt động trong ví dụ cụ thể được cung cấp, nhưng vẫn còn một nguồn cấp dữ liệu bổ sung được sản xuất bởi Write-Output, bạn không thể nhìn thấy nó bởi vì đó là điều cuối cùng được viết. Cách giải quyết hợp lý, nhưng không phải là một giải pháp. Có thể có một cái gì đó tiêu thụ đầu ra kết quả mà không thể xử lý dòng mới.
Slogmeister Extraordinaire

1
Không chính xác. Giải pháp không thể được thực hiện với một lệnh duy nhất.
Majkinetor

Điều này không giải quyết câu hỏi. Đầu ra tệp nhật ký sẽ hiển thị thao tác sắp được thử để có thể nhìn thấy và theo dõi lỗi. Sự kết hợp không đạt được điều đó.
Durette

0

Sau đây sẽ đặt con trỏ trở lại ở đầu hàng trước. Tùy thuộc vào bạn để đặt nó ở vị trí nằm ngang bên phải (sử dụng $ pos.X để di chuyển nó sang một bên):

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

Đầu ra hiện tại của bạn là 27 khoảng trắng, vì vậy $ pos.X = 27 có thể hoạt động.


Điều này không có gì để làm với đầu ra tập tin.
Slogmeister Extraordinaire

Nó cũng không tệ. Nó có thể tạo ra đầu ra chính xác nếu bạn $pos.Xcũng làm . Vấn đề là nếu bạn dẫn nó vào một tập tin, hai dòng riêng biệt xuất hiện.
Majkinetor

0

Nó có thể không thanh lịch khủng khiếp, nhưng nó thực hiện chính xác những gì OP yêu cầu. Lưu ý rằng ISE gây rối với StdOut, do đó sẽ không có đầu ra. Để xem tập lệnh này hoạt động, nó không thể được chạy trong 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
Không chính xác. Nếu bạn đặt nó vào một tập tin và đường ống đầu ra của nó thì không có gì xuất hiện.
Majkinetor

Đường ống đến một tập tin không phải là thứ mà OP yêu cầu. Và có, [System.Console]không thể được chuyển hướng đến một tập tin.
Slogmeister Extraordinaire

0

Tôi đã lừa dối, nhưng tôi tin rằng đây là câu trả lời duy nhất giải quyết mọi yêu cầu. Cụ thể, điều này tránh CRLF kéo dài, cung cấp một vị trí cho hoạt động khác hoàn thành trong thời gian này và chuyển hướng chính xác đến thiết bị xuất chuẩn khi cần thiết.

$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 mong muốn: Kích hoạt tính năng XYZ ...... Xong

bạn có thể sử dụng lệnh dưới đây

$ a = "Kích hoạt tính năng XYZ"

Đầu ra ghi "$ a ...... Xong"

bạn phải thêm biến và tuyên bố bên trong dấu ngoặc kép. hy vọng điều này hữu ích :)

Cảm ơn Techiegal


Đầu ra ghi được ưu tiên để đưa các đối tượng ra đường ống. Để hiển thị văn bản, Máy chủ ghi thường xuyên được sử dụng và gần đây, Thông tin ghi được sử dụng để ghi vào luồng Thông tin.
Logicdiagram

0

Có rất nhiều câu trả lời ở đây rồi, không ai sẽ cuộn xuống đây. Dù sao, cũng có một giải pháp để viết văn bản mà không có một dòng mới ở cuối, với những điều sau đây:

Đầu ra tệp có mã hóa:

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

Sản lượng an ủi:

  # 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

Bạn hoàn toàn có thể làm điều này. Đầu ra ghi có một cờ gọi là " NoEnum Cả " về cơ bản là giống nhau.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.