控制台中的简单进度指示

发布于 2024-12-28 06:10:19 字数 101 浏览 2 评论 0原文

在控制台中指示工作进度的最简单方法是什么?输出百分比就够了,不需要进度条。

仅使用 print 会产生很多行,我只想在终端中使用一个变化的字符串。

What is the easiest way to indicate the work progress in console? Outputting the percentage will be enough, progress bar is not necessary.

Using just print will produce lot's of lines, I want just a single changing string in a terminal.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

与往事干杯 2025-01-04 06:10:19

最简单的方法是像 wget 和其他程序一样:在进度信息之前打印出回车符和 ANSI 擦除行代码,从而将光标返回到行的开头并替换现有文本。例如:

import Control.Monad
import Control.Concurrent
import System.IO
import Text.Printf

putProgress :: String -> IO ()
putProgress s = hPutStr stderr $ "\r\ESC[K" ++ s

drawProgressBar :: Int -> Rational -> String
drawProgressBar width progress =
  "[" ++ replicate bars '=' ++ replicate spaces ' ' ++ "]"
  where bars = round (progress * fromIntegral width)
        spaces = width - bars

drawPercentage :: Rational -> String
drawPercentage progress = printf "%3d%%" (truncate (progress * 100) :: Int)

main :: IO ()
main = do
  forM_ [0..10] $ \i -> do
    let progress = fromIntegral i / 10
    putProgress $ drawProgressBar 40 progress ++ " " ++ drawPercentage progress
    threadDelay 250000
  putProgress "All done."
  hPutChar stderr '\n'

这里的关键是打印换行符,以便您可以在下一次进度更新时返回到行的开头。

当然,您可以在此处打印出百分比并删除栏,但栏更酷:)

The simplest way would be to do what wget and other programs do: printing out a carriage return and an ANSI erase-line code before the progress information, thus returning the cursor to the start of the line and replacing the existing text. For example:

import Control.Monad
import Control.Concurrent
import System.IO
import Text.Printf

putProgress :: String -> IO ()
putProgress s = hPutStr stderr $ "\r\ESC[K" ++ s

drawProgressBar :: Int -> Rational -> String
drawProgressBar width progress =
  "[" ++ replicate bars '=' ++ replicate spaces ' ' ++ "]"
  where bars = round (progress * fromIntegral width)
        spaces = width - bars

drawPercentage :: Rational -> String
drawPercentage progress = printf "%3d%%" (truncate (progress * 100) :: Int)

main :: IO ()
main = do
  forM_ [0..10] $ \i -> do
    let progress = fromIntegral i / 10
    putProgress $ drawProgressBar 40 progress ++ " " ++ drawPercentage progress
    threadDelay 250000
  putProgress "All done."
  hPutChar stderr '\n'

The key thing here is to not print a newline, so that you can return to the start of the line on the next progress update.

Of course, you could just print out the percentage here and drop the bar, but a bar is cooler :)

☆獨立☆ 2025-01-04 06:10:19

如果我想要一些非常快速和肮脏的东西,我倾向于做的就是打印一系列点。每当有“更多”进展时,我就再写一个点(没有换行符)。我调整了“一点进展”的衡量标准,以便点在每秒一个点的时间尺度上出现。不是很复杂,但它表明程序正在做一些事情。

如果您实际上对总“进度”有某种衡量标准(我经常没有,但这是通过您提到的百分比建议的),那么您可以将整个程序声明为 X 点,并且每次取得 1/X 进度时打印一份。

If I want something really quick and dirty, what I tend to do is just print a sequence of dots. Every time there's been "a bit more" progress I just write another dot (with no newline). I tune the measure of "a bit of progress" so that the dots come on about the time scale of a dot per second. Not very sophisticated, but it shows the program is doing something.

If you actually have some sort of measure of how much total "progress" there will be (I often don't, but this is suggested by your mention of percentages), then you can just declare the whole program to be X dots, and print one every time you make 1/X progress.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文