如何在Linux Shell中实现多行输出原地刷新覆盖?
你之前的代码失效的核心原因是 \r 仅能将光标回退到当前行的行首,而你grep得到的$OUTP变量中自带多行换行符,输出时会自动换行到新行,最终只有最后一行会被\r覆盖,之前的行都会永久保留在终端中,导致内容不断堆叠。
可行解决方案
根据使用场景可以选择以下几种方案:
方案1:直接使用watch命令(最简单,适合独立监控场景)
不需要自己写循环,系统自带的watch命令默认就支持原地刷新内容,直接执行即可:
watch -n 5 'df -h | grep sda'
参数说明:-n 5指定刷新间隔为5秒,命令输出会自动原地刷新,不会有内容残留。
方案2:ANSI转义序列实现(适合嵌入自定义脚本)
通过终端ANSI控制序列手动控制光标位置和旧内容清除,兼容性覆盖绝大多数现代终端:
# 首次输出初始内容 OUTP=$(df -h | grep sda) echo -e "$OUTP" # 统计输出行数,用于控制光标上移距离 line_count=$(echo "$OUTP" | wc -l) # 后续循环刷新 for i in {1..99}; do sleep 5 # 光标上移line_count行,同时清除光标到屏幕末尾的所有旧内容 echo -ne "\033[${line_count}A\033[J" # 输出新内容 OUTP=$(df -h | grep sda) echo -e "$OUTP" # 可选:如果sda分区数量可能动态变化,每次刷新后重新统计行数 line_count=$(echo "$OUTP" | wc -l) done
方案3:tput命令实现(兼容性更强)
如果需要适配非常老的终端,用tput调用系统terminfo数据库生成控制序列,不需要手动记忆ANSI码:
OUTP=$(df -h | grep sda) echo -e "$OUTP" line_count=$(echo "$OUTP" | wc -l) for i in {1..99}; do sleep 5 # 光标上移line_count行 tput cuu "$line_count" # 清除光标到屏幕结尾的所有内容 tput ed OUTP=$(df -h | grep sda) echo -e "$OUTP" line_count=$(echo "$OUTP" | wc -l) done
内容的提问来源于stack exchange,提问作者DenisZ
相关产品推荐
相关产品推荐

