Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/shell/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Bash 带有其他输出的命令行进度条_Bash_Shell_Terminal - Fatal编程技术网

Bash 带有其他输出的命令行进度条

Bash 带有其他输出的命令行进度条,bash,shell,terminal,Bash,Shell,Terminal,在命令行上获取进度条的一种常用方法是使用回车符,它覆盖上一行,如本脚本所示: #!/bin/bash echo -ne '[# ] 25%\r' sleep 1 echo -ne '[## ] 50%\r' sleep 1 echo -ne '[### ] 75%\r' sleep 1 echo -ne '[####] 100%\r' 这没关系。。。如果只想打印进度条。但更复杂的脚本可能希望在输出诊断输出的同时打印进度条。您希望命令行应用程序的缓冲区按如下方式发展(用---分隔): 现在

在命令行上获取进度条的一种常用方法是使用回车符,它覆盖上一行,如本脚本所示:

#!/bin/bash
echo -ne '[#   ] 25%\r'
sleep 1
echo -ne '[##  ] 50%\r'
sleep 1
echo -ne '[### ] 75%\r'
sleep 1
echo -ne '[####] 100%\r'
这没关系。。。如果只想打印进度条。但更复杂的脚本可能希望在输出诊断输出的同时打印进度条。您希望命令行应用程序的缓冲区按如下方式发展(用
---
分隔):

现在,流行的方法失败了:

#!/bin/bash
echo -ne '[#   ] 25%\r'
echo "msg 1"
sleep 1
echo "msg 2"
echo -ne '[##  ] 50%\r'
echo "msg 3"
sleep 1
echo "msg 4"
echo -ne '[### ] 75%\r'
sleep 1
echo -ne '[####] 100%\r'
输出

ezyang@sabre:~$ ./test.sh 
msg 1] 25%
msg 2
msg 3] 50%
msg 4
似乎要实现这一点,您需要在其他任何时候打印邮件:

  • 检查它是否是进度条
  • 如果是,请清除该行,打印输出加上换行符,然后重新打印进度条
  • (或者,您可以使用ncurses)。不幸的是,这需要每一个可能的东西,可以给输出玩球

    是否有任何模块化方法可以使这种进度条正常工作,而不需要检测所有其他输出到终端的方法?

    更新: 您可以使用ANSI/VT100转义码/序列执行此操作

    在添加工作示例之前,您需要了解以下几点:

    • 您需要确保输出到TTY/控制台

    • 您需要了解IO(标准输出/标准输出)之间的区别 线,和TTY线。
      \r
      将引导您找到IO行的开头,即使该行跨越多条TTY行

    • Windows控制台本机不支持这些代码/序列。但您可以在(推荐)中使用它们,也可以与一起使用


    下面是一个工作示例。代码应该是不言自明的:

     #!/bin/bash
    
     ERASE_SCREEN_AFTER="\033[0J"
     ERASE_LINE_BEFORE="\033[1K"
     ERASE_LINE_AFTER="\033[0K"
     UP="\033[1A"
    
     up_count=2
     messages="\n"
     progress=""
    
     echo_repeat() {
       c="$2"
       while (( c )); do
         echo -en "$1"
         (( c-- ))
       done
     }
    
     update_status() {
       echo_repeat "$UP" "$up_count"
       echo -en "$ERASE_LINE_BEFORE" "$ERASE_SCREEN_AFTER" "\r"
       echo -en "$messages"
       echo "$progress"
     }
    
     add_msg() {
       messages+="$@\n"
       update_status
       (( up_count++ ))
     }
    
     set_progress() {
       progress="$@"
       update_status
     }
    
     echo_repeat "\n" $up_count
    
     set_progress '[#   ] 25%'
     add_msg "msg 1"
     sleep 1
    
     add_msg "msg 2"
     set_progress '[##  ] 50%'
     add_msg "msg 3"
     sleep 1
    
     add_msg "msg 4"
     set_progress '[### ] 75%'
     sleep 1
    
     set_progress '[####] 100%'
    
    您可以单独使用这些代码/序列,而不使用 (n) 诅咒。这包括设置前景/背景色、使用粗体字体以及其他功能

    是广泛使用这些代码/序列的CLI程序示例



    旧答案(过时):如果我正确理解您的问题,您只需在
    msg
    行之前添加一个
    \n

    在消息之前添加一个新行意味着进度消息永远不会被删除;我希望删除旧的进度消息。因此,您需要两行更新行。一个用于进度,一个用于消息?不是两行更新;消息可以是单调增加的。我很高兴地假设只有一条路可以前进。因此,您只需要在进度行之前打印消息。我会更新我的答案。
     #!/bin/bash
    
     ERASE_SCREEN_AFTER="\033[0J"
     ERASE_LINE_BEFORE="\033[1K"
     ERASE_LINE_AFTER="\033[0K"
     UP="\033[1A"
    
     up_count=2
     messages="\n"
     progress=""
    
     echo_repeat() {
       c="$2"
       while (( c )); do
         echo -en "$1"
         (( c-- ))
       done
     }
    
     update_status() {
       echo_repeat "$UP" "$up_count"
       echo -en "$ERASE_LINE_BEFORE" "$ERASE_SCREEN_AFTER" "\r"
       echo -en "$messages"
       echo "$progress"
     }
    
     add_msg() {
       messages+="$@\n"
       update_status
       (( up_count++ ))
     }
    
     set_progress() {
       progress="$@"
       update_status
     }
    
     echo_repeat "\n" $up_count
    
     set_progress '[#   ] 25%'
     add_msg "msg 1"
     sleep 1
    
     add_msg "msg 2"
     set_progress '[##  ] 50%'
     add_msg "msg 3"
     sleep 1
    
     add_msg "msg 4"
     set_progress '[### ] 75%'
     sleep 1
    
     set_progress '[####] 100%'