如何在Bash中显示和刷新多行

13

我正在编写一个安装脚本,并希望在脚本执行过程中显示脚本的状态。

例如:

var1="pending"
var2="pending"
var3="pending"

print_status () {
echo "Status of Item 1 is: "$var1""
echo "Status of Item 2 is: "$var2""
echo "Status of Item 3 is: "$var3""
}

code that does something and then refreshes the
output above as the status of each variable changes.

尝试使用 clear 命令,它可以清除屏幕。如果需要更高级的操作,请使用类似 dialog 的工具。 - choroba
1
你能澄清一下你所说的“刷新”是什么意思吗?你是想要一个只更新某些字段的“表单”或“屏幕”输出吗?而且在同一时间可能会有多个这样的字段吗?还是item2的状态只有在item1完成后才开始(同样,item3在item2之后)? - lurker
5个回答

30

这段代码应该能给你一个想法:

while :; do
    echo "$RANDOM"
    echo "$RANDOM"
    echo "$RANDOM"
    sleep 0.2
    tput cuu1 # move cursor up by one line
    tput el # clear the line
    tput cuu1
    tput el
    tput cuu1
    tput el
done

使用man tput获取更多信息。要查看能力列表,请使用man terminfo


1
谢谢。我从未听说过tput。 - seanmcl
3
如果你打算在这方面大展拳脚,我建议使用curses(一种编程库)。http://en.wikipedia.org/wiki/Curses_(programming_library) - seanmcl

7

我发现另一种解决方案,这在现有的答案中没有提到。我正在为openwrt开发程序,而tput默认不可用。下面的解决方案是受到Missing tputCursor Movement的启发。

- Position the Cursor:
  \033[<L>;<C>H
     Or
  \033[<L>;<C>f
  puts the cursor at line L and column C.
- Move the cursor up N lines:
  \033[<N>A
- Move the cursor down N lines:
  \033[<N>B
- Move the cursor forward N columns:
  \033[<N>C
- Move the cursor backward N columns:
  \033[<N>D

- Clear the screen, move to (0,0):
  \033[2J
- Erase to end of line:
  \033[K

- Save cursor position:
  \033[s
- Restore cursor position:
  \033[u

关于你的问题:
var1="pending"
var2="pending"
var3="pending"

print_status () {
    # add \033[K to truncate this line
    echo "Status of Item 1 is: "$var1"\033[K"
    echo "Status of Item 2 is: "$var2"\033[K"
    echo "Status of Item 3 is: "$var3"\033[K"
}

while true; do 
    print_status
    sleep 1
    printf "\033[3A"    # Move cursor up by three line
done

3

看一下这个:

while true; do echo -ne "`date`\r"; done

还有这个:

declare arr=(
  ">...."
  ".>..."
  "..>.."
  "...>."
  "....>"
)

for i in ${arr[@]}
do
  echo -ne "${i}\r"
  sleep 0.1
done

1
您可以使用回车符来更改单个状态行上的文本。
n=0
while true; do
  echo -n -e "n: $n\r"
  sleep 1
  n=$((n+1))
done

如果您可以将所有计数器放在一行上
n=0
m=100
while true; do
  echo -n -e "n: $n  m: $m\r"
  sleep 1
  n=$((n+1))
  m=$((m-1))
done

这种技术似乎无法扩展到多行,尽管它比tput更有优势,因为它可以在哑终端上使用(例如Emacs shell)。


0
这并不能完全解决你的问题,但可能会有所帮助;要在每个命令执行后打印状态,请像这样修改PS1:
PS1='$PS1 $( print_status )'

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接