雇用(浮点)进度条
序言
对不起,这个不是那么短的答案。
对于不耐烦的人:请在 现在开始测试代码!(在中间),最后动画演示(在此底部。)
这里的所有演示都使用read -t <float seconds> && break 而不是sleep。所以所有循环都可以通过点击 Return 键很好地停止。
简介
又一个 Bash 进度条...
由于这里已经有很多答案,我想添加一些关于性能和精度.
1。避免分叉!
因为进度条是为了在其他进程正在运行时运行,所以这一定是一个不错进程...
因此,在不需要时避免使用 forks。示例:而不是
mysmiley=$(printf '%b' \\U1F60E)
使用
printf -v mysmiley '%b' \\U1F60E
解释:当你运行var=$(command)时,你启动了一个新进程来执行command并将他的输出发送到变量$var em> 一旦终止。这是非常资源昂贵。请比较:
TIMEFORMAT="%R"
time for ((i=2500;i--;)){ mysmiley=$(printf '%b' \\U1F60E);}
2.292
time for ((i=2500;i--;)){ printf -v mysmiley '%b' \\U1F60E;}
0.017
bc -l <<<'2.292/.017'
134.82352941176470588235
在我的主机上,分配 $mysmiley 的相同工作(仅 2500 次),使用 fork 似乎比使用内置 printf -v 慢约 135 倍/更昂贵。
然后
echo $mysmiley
?
所以你的 function 必须不打印(或输出)任何东西。您的函数必须将他的答案归因于一个变量。
2。使用整数作为伪浮点数
这是一个非常小而快速的函数,用于从整数计算百分比,使用整数并回答伪浮点数:
percent(){
local p=00$(($1*100000/$2))
printf -v "$3" %.2f ${p::-3}.${p: -3}
}
用法:
# percent <integer to compare> <reference integer> <variable name>
percent 33333 50000 testvar
printf '%8s%%\n' "$testvar"
66.67%
3。使用 UTF-8 租用控制台图形:▏ ▎ ▍ ▌ ▋ ▊ ▉ █
要使用 bash 渲染这些字符,您可以:
printf -v chars '\\U258%X ' {15..8}
printf "$chars\\n"
▏ ▎ ▍ ▌ ▋ ▊ ▉ █
那么我们必须使用 8x string with 作为 graphic width。
现在就做吧!
这个函数被命名为percentBar,因为它会根据以百分比(浮动)提交的参数呈现一个条形:
percentBar () {
local prct totlen=$((8*$2)) lastchar barstring blankstring;
printf -v prct %.2f "$1"
((prct=10#${prct/.}*totlen/10000, prct%8)) &&
printf -v lastchar '\\U258%X' $(( 16 - prct%8 )) ||
lastchar=''
printf -v barstring '%*s' $((prct/8)) ''
printf -v barstring '%b' "${barstring// /\\U2588}$lastchar"
printf -v blankstring '%*s' $(((totlen-prct)/8)) ''
printf -v "$3" '%s%s' "$barstring" "$blankstring"
}
用法:
# percentBar <float percent> <int string width> <variable name>
percentBar 42.42 $COLUMNS bar1
echo "$bar1"
█████████████████████████████████▉
为了显示小的差异:
percentBar 42.24 $COLUMNS bar2
printf "%s\n" "$bar1" "$bar2"
█████████████████████████████████▉
█████████████████████████████████▊
有颜色
由于渲染变量是固定宽度的字符串,所以使用颜色很容易:
percentBar 72.1 24 bar
printf 'Show this: \e[44;33;1m%s\e[0m at %s%%\n' "$bar" 72.1
小动画:
for i in {0..10000..33} 10000;do i=0$i
printf -v p %0.2f ${i::-2}.${i: -2}
percentBar $p $((COLUMNS-9)) bar
printf '\r|%s|%6.2f%%' "$bar" $p
read -srt .002 _ && break # console sleep avoiding fork
done
|███████████████████████████████████████████████████████████████████████|100.00%
clear; for i in {0..10000..33} 10000;do i=0$i
printf -v p %0.2f ${i::-2}.${i: -2}
percentBar $p $((COLUMNS-7)) bar
printf '\r\e[47;30m%s\e[0m%6.2f%%' "$bar" $p
read -srt .002 _ && break
done
最后的动画演示
另一个展示不同尺寸和彩色输出的演示:
printf '\n\n\n\n\n\n\n\n\e[8A\e7'&&for i in {0..9999..99} 10000;do
o=1 i=0$i;printf -v p %0.2f ${i::-2}.${i: -2}
for l in 1 2 3 5 8 13 20 40 $((COLUMNS-7));do
percentBar $p $l bar$((o++));done
[ "$p" = "100.00" ] && read -rst .8 _;printf \\e8
printf '%s\e[48;5;23;38;5;41m%s\e[0m%6.2f%%%b' 'In 1 char width: ' \
"$bar1" $p ,\\n 'with 2 chars: ' "$bar2" $p ,\\n 'or 3 chars: ' \
"$bar3" $p ,\\n 'in 5 characters: ' "$bar4" $p ,\\n 'in 8 chars: ' \
"$bar5" $p .\\n 'There are 13 chars: ' "$bar6" $p ,\\n '20 chars: '\
"$bar7" $p ,\\n 'then 40 chars' "$bar8" $p \
', or full width:\n' '' "$bar9" $p ''
((10#$i)) || read -st .5 _; read -st .1 _ && break
done
可以产生这样的东西: