将 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
}
我有一段 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
}
注意:只要下一个输出的长度等于或大于(在您的情况下是这样),这就是您所需要的。否则你必须先清除最后一个输出。
"`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
}