将 PowerShell 输出字符串覆盖到同一行

Overwrite PowerShell output strings onto the same line

我有一段 PS 代码,它获取 7-Zip 提取输出并将其过滤掉,因此只打印百分比“%”的进度更新行。我已经设法将其减少到仅百分比输出:

& ZipPath "x" $filePath "-o$extractionPath" "-aos" "-bsp1" | out-string -stream | Select-String -Pattern "\d{1,3}%" -AllMatches | ForEach-Object { $_.Matches.Value } | Write-Host -NoNewLine

目前控制台输出如下所示:

0%1%5%9%14%17%20%23%26%31%37%43%46%48%50%52%54%56%59%61%63%65%67%70%72%74%76%78%80%81%82%83%85%86%87%89%90%91%92%94%95%96%97%98%99%

有没有办法将这些输出保持在同一个地方,在同一条线上,使它们相互覆盖?这很棘手,因为输出是从 7-Zip 应用程序通过管道传输的。恐怕我无法使用 Expand-Archive,因为我正在处理 .7z 个文件

非常感谢!

您可以使用 .Net System.Console class:

[System.Console]::SetCursorPosition(0, [System.Console]::CursorTop)

因此您的代码必须是:

& ZipPath "x" $filePath "-o$extractionPath" "-aos" "-bsp1" | out-string -stream | Select-String -Pattern "\d{1,3}%" -AllMatches | ForEach-Object { $_.Matches.Value } | foreach {
    [System.Console]::SetCursorPosition(0, [System.Console]::CursorTop) 
    Write-Host $_ -NoNewLine
}

注意:只要下一个输出的长度等于或大于(在您的情况下是这样),这就是您所需要的。否则你必须先清除最后一个输出。

效果很好,但还有一个更简单的替代方法,即使用 CR 字符 ("`r") 将光标位置重置为行首。

这是在同一行打印数字 1 到 10 的简单演示:

1..10 | ForEach-Object { Write-Host -NoNewline "`r$_"; Start-Sleep -Milliseconds 100 }

[Console]::Write(...) 而不是 Write-Host -NoNewline ... 也有效,正如 Bacon Bits 指出的那样。

同样的约束适用,但是:如果前面的输出行恰好 更长,额外的字符 linger.

同样要解决这个问题,您必须将任何输出行填充到控制台 window 的缓冲区宽度的长度:

'loooooooong', 'meeedium', 'short' | ForEach-Object { 
   Write-Host -NoNewline ("`r{0,-$([console]::BufferWidth)}" -f $_)
   Start-Sleep -Milliseconds 500 
}