100% pur bash uniquement! Sans fourchette!
Une version finalisée et améliorée peut être trouvée ici ou sur cette page:
ascii-clock for geeks . Mais ne l'utilisez pas! Lisez la note à la fin de cette réponse, vous avez été prévenu! Utilisez plutôt cette version Perl !
Première horloge simple sans deuxième tick.
Évolutif et modifiable:
time 2>&1 /tmp/asci-art.sh 10 10 10
. . . 12. . .
11. . 1
. .
. .
. .
10 2
. H M .
. .
. .
. .
9 3
. .
. .
. .
. .
8 4
. .
. .
. .
7 . . 5
. . . 6 . . .
real 0m0.356s
user 0m0.348s
sys 0m0.004s
Dessinez une horloge 21x21 (10x2 + 1) à 10H10 en moins d'une seconde.
Cela accepte 3 arguments: Usage: ascii-clock.sh [ray of clock] [Hour] [Min]où le rayon par défaut est 12, le dessin de l'horloge est la 2 x ray + 1hauteur des lignes et la double largeur en raison de l'espace ajouté pour essayer d'obtenir une forme ronde.
Si le script est appelé avec 0ou 1argument, il se mettra en boucle pour être redessiné chaque minute. Sinon si au moins Heure (deuxième paramètre) est spécifié, il ne dessinera qu'une seule fois et sortira.
Le Hmarqueur est situé à 70% du rayon et le Mmarqueur est situé à 90% du rayon.
Pas d'utilisation de binaires externes comme dateoubc pour le tirage!
(Merci à @manatwork pour la fonction intégrée read -t si /bin/sleep).
Tout cela est donc fait par des commandes shell intégrées .
Il utilise la séquence ANSI , mais uniquement pour la boucle et pour mettre les marqueurs en gras.
#!/bin/bash
# Analog clock in Ascii-Art written in BASH V4.2 +=
RAY=${1:-12} NowH=$2 NowM=$3
sqrt() {
local -a _xx=(600000 200000)
local _x1=${_xx[$(($1&1))]} _x0=1
while [ $_x0 -ne $_x1 ] ;do
_x0=$_x1
[ $_x0 -eq 0 ] && _x1=0000 ||
printf -v _x1 "%u" $(( (${_x0}000 + ${1}00000000000/${_x0} )/2 ))
printf -v _x1 "%.0f" ${_x1:0:${#_x1}-3}.${_x1:${#_x1}-3}
done
_x1=0000$_x1
printf ${2+-v} $2 "%.3f" ${_x1:0:${#_x1}-4}.${_x1:${#_x1}-4}
}
clksin() { # $1:moment [0-60], $2:path length, $3:variable name
local _csin=(0 104528 207912 309017 406737 500000 587785 669131
743145 809017 866025 913545 951057 978148 994522 1000000)
local xsign=1 x=$1 ysign=-1 y=$1
[ $x -gt 30 ] && xsign=-1 x=$((60-x))
[ $x -gt 15 ] && x=$((30-x))
x=00000$((RAY*1000000+xsign*${2:-10}*${_csin[$x]}))
[ $y -gt 30 ] && y=$((60-y))
[ $y -gt 15 ] && ysign=1 y=$((30-y))
y=00000$((RAY*1000000+ysign*${2:-10}*${_csin[15-$y]}))
printf ${3+-v} $3 "%.0f %.0f" \
${y:0:${#y}-6}.${y:${#y}-6} ${x:0:${#x}-6}.${x:${#x}-6}
};
MLEN=000$((900*RAY))
printf -v MLEN "%.0f" ${MLEN:0:${#MLEN}-3}.${MLEN:${#MLEN}-3}
HLEN=000$((700*RAY))
printf -v HLEN "%.0f" ${HLEN:0:${#HLEN}-3}.${HLEN:${#HLEN}-3}
declare -A ticks
for ((i=1;i<=12;i++));do
clksin $((5*(i%12))) $RAY tick
ticks[$tick]=$i
done
while :;do
[ "$NowM" ] || printf -v NowM "%(%M)T\n" -1
clksin ${NowM#0} $MLEN NowM
[ "$NowH" ] || printf -v NowH "%(%H)T\n" -1
clksin $((5*(${NowH#0}%12))) $HLEN NowH
[ "$2" ] || echo -en \\e[H; # ANSI sequence for top left of console
for ((i=0;i<=2*RAY;i++));do
x=$((RAY-i))
sqrt $((RAY**2 - ${x#-}**2 )) y0
printf -v y0 "%.0f" $y0
for ((l=0;l<=2*RAY;l++));do
y=$((RAY-l));
sqrt $((RAY**2 - ${y#-}**2 )) x0
printf -v x0 "%.0f" $x0
if [ "${ticks["$i $l"]}" ] ;then
printf "%-2s" ${ticks["$i $l"]}
elif [ ${x#-} -eq $x0 ] || [ ${y#-} -eq $y0 ] ;then
echo -n .\
elif [ "$i $l" = "$NowM" ] ;then
echo -en \\e[1mM\ \\e[0m
elif [ "$i $l" = "$NowH" ] ;then
echo -en \\e[1mH\ \\e[0m
else
echo -n \ \
fi
done
echo -e \\e[K
done
echo -en \\e[J
[ "$2" ] && break # Exit if at least Hour was specified
printf -v SleepS "%(%S)T" -1
read -t $((60-${SleepS#0})) foo
unset NowH NowM
done
Cela pourrait être exécuté comme:
for time in 10:10 15:00 12:30 06:00 09:15 16:40 ;do
echo - $time -{,}{,}{,}
./ascii-clock.sh 5 ${time//:/ }
echo -{,,,,,}{,}
done |
sed 's/\o033\[\(.m\|[JK]\)//g;/-$/!s/$/|/;s/-$/+/' |
column -c 80
Cela produira quelque chose comme:
+- 10:10 - - - - - - - + - 12:30 - - - - - - - + - 09:15 - - - - - - - +
| . . 12. . | . . 12. . | . . 12. . |
| 11 1 | 11 H 1 | 11 1 |
| 10 2 | 10 2 | 10 2 |
|. H M . | . . | . . |
|. . | . . | . . |
|9 3 | 9 3 | 9 H M 3 |
|. . | . . | . . |
|. . | . . | . . |
| 8 4 | 8 4 | 8 4 |
| 7 5 | 7 M 5 | 7 5 |
| . . 6 . . | . . 6 . . | . . 6 . . |
+- - - - - - - - - - - + - - - - - - - - - - - + - - - - - - - - - - - +
+- 15:00 - - - - - - - + - 06:00 - - - - - - - + - 16:40 - - - - - - - +
| . . 12. . | . . 12. . | . . 12. . |
| 11 M 1 | 11 M 1 | 11 1 |
| 10 2 | 10 2 | 10 2 |
|. . | . . | . . |
|. . | . . | . . |
|9 H 3 | 9 3 | 9 3 |
|. . | . . | . . |
|. . | . . | . M H . |
| 8 4 | 8 4 | 8 4 |
| 7 5 | 7 H 5 | 7 5 |
| . . 6 . . | . . 6 . . | . . 6 . . |
+- - - - - - - - - - - + - - - - - - - - - - - + - - - - - - - - - - - +
Ou pourrait être exécuté comme:
xterm -geom 86x44 -bg black -fg grey -e ./ascii-clock.sh 21 &
xterm -geom 103x52 -fn nil2 -bg black -fg grey -e ./ascii-clock.sh 25 &
gnome-terminal --geometry 103x52 --zoom .5 -e "./ascii-clock.sh 25" &
Alternative: Avec dessin de chemin complet:
#!/bin/bash
# Analog clock in Ascii-Art written in BASH V4.2 +=
RAY=${1:-12} NowH=$2 NowM=$3
sqrt() {
local -a _xx=(600000 200000)
local _x1=${_xx[$(($1&1))]} _x0=1
while [ $_x0 -ne $_x1 ] ;do
_x0=$_x1
[ $_x0 -eq 0 ] && _x1=0000 ||
printf -v _x1 "%u" $(( (${_x0}000 + ${1}00000000000/${_x0} )/2 ))
printf -v _x1 "%.0f" ${_x1:0:${#_x1}-3}.${_x1:${#_x1}-3}
done
_x1=0000$_x1
printf ${2+-v} $2 "%.3f" ${_x1:0:${#_x1}-4}.${_x1:${#_x1}-4}
}
clksin() { # $1:moment [0-60], $2:path length, $3:variable name
local _csin=(0 104528 207912 309017 406737 500000 587785 669131
743145 809017 866025 913545 951057 978148 994522 1000000)
local xsign=1 x=$1 ysign=-1 y=$1
[ $x -gt 30 ] && xsign=-1 x=$((60-x))
[ $x -gt 15 ] && x=$((30-x))
x=00000$((RAY*1000000+xsign*${2:-10}*${_csin[$x]}))
[ $y -gt 30 ] && y=$((60-y))
[ $y -gt 15 ] && ysign=1 y=$((30-y))
y=00000$((RAY*1000000+ysign*${2:-10}*${_csin[15-$y]}))
printf ${3+-v} $3 "%.0f %.0f" \
${y:0:${#y}-6}.${y:${#y}-6} ${x:0:${#x}-6}.${x:${#x}-6}
};
MLEN=000$((900*RAY))
printf -v MLEN "%.0f" ${MLEN:0:${#MLEN}-3}.${MLEN:${#MLEN}-3}
HLEN=000$((700*RAY))
printf -v HLEN "%.0f" ${HLEN:0:${#HLEN}-3}.${HLEN:${#HLEN}-3}
declare -A ticks
for ((i=1;i<=12;i++));do
clksin $((5*(i%12))) $RAY tick
ticks[$tick]=$i
done
while :;do
[ "$NowM" ] || printf -v NowM "%(%M)T\n" -1
unset MPath
declare -A MPath
for ((i=1;i<=MLEN;i++));do
clksin ${NowM#0} $i tick
MPath[$tick]=M
done
[ "$NowH" ] || printf -v NowH "%(%H)T\n" -1
unset HPath
declare -A HPath
for ((i=1;i<=HLEN;i++));do
clksin $((5*(${NowH#0}%12))) $i tick
HPath[$tick]=H
done
[ "$2" ] || echo -en \\e[H; # ANSI sequence for top left of console
for ((i=0;i<=2*RAY;i++));do
x=$((RAY-i))
sqrt $((RAY**2 - ${x#-}**2 )) y0
printf -v y0 "%.0f" $y0
for ((l=0;l<=2*RAY;l++));do
y=$((RAY-l));
sqrt $((RAY**2 - ${y#-}**2 )) x0
printf -v x0 "%.0f" $x0
if [ "${MPath["$i $l"]}" ] ;then
echo -en \\e[1m${MPath["$i $l"]}\ \\e[0m
elif [ "${HPath["$i $l"]}" ] ;then
echo -en \\e[1m${HPath["$i $l"]}\ \\e[0m
elif [ "${ticks["$i $l"]}" ] ;then
printf "%-2s" ${ticks["$i $l"]}
elif [ ${x#-} -eq $x0 ] || [ ${y#-} -eq $y0 ] ;then
echo -n .\
else
echo -n \ \
fi
done
echo -e \\e[K
done
echo -en \\e[J
[ "$2" ] && break # Exit if at least Hour was specified
printf -v SleepS "%(%S)T" -1
read -t $((60-${SleepS#0})) foo
unset NowH NowM
done
pourrait produire:
+- 10:10 - - - - - - - + - 12:30 - - - - - - - + - 09:15 - - - - - - - +
| . . 12. . | . . 12. . | . . 12. . |
| 11 1 | 11 H 1 | 11 1 |
| 10 2 | 10 H 2 | 10 2 |
|. H M . | . H . | . . |
|. H H H M M M . | . H . | . . |
|9 3 | 9 3 | 9 H H H H M M M M 3 |
|. . | . M . | . . |
|. . | . M . | . . |
| 8 4 | 8 M 4 | 8 4 |
| 7 5 | 7 M 5 | 7 5 |
| . . 6 . . | . . 6 . . | . . 6 . . |
+- - - - - - - - - - - + - - - - - - - - - - - + - - - - - - - - - - - +
+- 15:00 - - - - - - - + - 06:00 - - - - - - - + - 16:40 - - - - - - - +
| . . 12. . | . . 12. . | . . 12. . |
| 11 M 1 | 11 M 1 | 11 1 |
| 10 M 2 | 10 M 2 | 10 2 |
|. M . | . M . | . . |
|. M . | . M . | . . |
|9 H H H H 3 | 9 3 | 9 3 |
|. . | . H . | . M M M H H H . |
|. . | . H . | . M H . |
| 8 4 | 8 H 4 | 8 4 |
| 7 5 | 7 H 5 | 7 5 |
| . . 6 . . | . . 6 . . | . . 6 . . |
+- - - - - - - - - - - + - - - - - - - - - - - + - - - - - - - - - - - +
ou
. . . . 12. . . .
. . . . . .
. . . .
. 11 1 .
. .
. .
. .
. .
. .
. .
10 2
. M .
. M M M .
. H M .
. H H M M .
. H M .
. H H H M M M .
. H M .
. H H M M .
. H M .
9 H M 3
. .
. .
. .
. .
. .
. .
. .
. .
. .
8 4
. .
. .
. .
. .
. .
. .
. 7 5 .
. . . .
. . . . . .
. . . . 6 . . . .
Dernière version avec Secondes ticks rendu et nanosommeil à synchroniser.
Cela ne fonctionne que sur Linux récent, car cela permet /proc/timer_listde calculer la fraction de seconde pour dormir entre chaque rafraîchissement.
#!/bin/bash
# Analog clock in Ascii-Art written in BASH V4.2 +=
RAY=${1:-12} NowH=$2 NowM=$3
# Hires Sleep Until
# there is a need to store offset in a static var
mapfile </proc/timer_list _timer_list
for ((_i=0;_i<${#_timer_list[@]};_i++));do
[[ ${_timer_list[_i]} =~ ^now ]] && TIMER_LIST_SKIP=$_i
[[ ${_timer_list[_i]} =~ offset:.*[1-9] ]] && \
TIMER_LIST_OFFSET=${_timer_list[_i]//[a-z.: ]} && \
break
done
unset _i _timer_list
readonly TIMER_LIST_OFFSET TIMER_LIST_SKIP
sleepUntilHires() {
local slp tzoff now quiet=false nsnow nsslp
local hms=(${1//:/ })
mapfile -n 1 -s $TIMER_LIST_SKIP nsnow </proc/timer_list
printf -v now '%(%s)T' -1
printf -v tzoff '%(%z)T\n' $now
nsnow=$((${nsnow//[a-z ]}+TIMER_LIST_OFFSET))
nsslp=$((2000000000-10#${nsnow:${#nsnow}-9}))
tzoff=$((0${tzoff:0:1}(3600*${tzoff:1:2}+60*${tzoff:3:2})))
slp=$(( ( 86400 + ( now - now%86400 ) +
10#$hms*3600+10#${hms[1]}*60+10#${hms[2]} -
tzoff - now - 1
) % 86400)).${nsslp:1}
read -t $slp foo
}
sqrt() {
local -a _xx=(600000 200000)
local _x1=${_xx[$(($1&1))]} _x0=1
while [ $_x0 -ne $_x1 ] ;do
_x0=$_x1
[ $_x0 -eq 0 ] && _x1=0000 ||
printf -v _x1 "%u" $(( (${_x0}000 + ${1}00000000000/${_x0} )/2 ))
printf -v _x1 "%.0f" ${_x1:0:${#_x1}-3}.${_x1:${#_x1}-3}
done
_x1=0000$_x1
printf ${2+-v} $2 "%.3f" ${_x1:0:${#_x1}-4}.${_x1:${#_x1}-4}
}
clksin() { # $1:moment [0-60], $2:path length, $3:variable name
local _csin=(0 104528 207912 309017 406737 500000 587785 669131
743145 809017 866025 913545 951057 978148 994522 1000000)
local xsign=1 x=$1 ysign=-1 y=$1
[ $x -gt 30 ] && xsign=-1 x=$((60-x))
[ $x -gt 15 ] && x=$((30-x))
x=00000$((RAY*1000000+xsign*${2:-10}*${_csin[$x]}))
[ $y -gt 30 ] && y=$((60-y))
[ $y -gt 15 ] && ysign=1 y=$((30-y))
y=00000$((RAY*1000000+ysign*${2:-10}*${_csin[15-$y]}))
printf ${3+-v} $3 "%.0f %.0f" \
${y:0:${#y}-6}.${y:${#y}-6} ${x:0:${#x}-6}.${x:${#x}-6}
};
SLEN=000$((870*RAY))
printf -v SLEN "%.0f" ${SLEN:0:${#SLEN}-3}.${SLEN:${#SLEN}-3}
MLEN=000$((780*RAY))
printf -v MLEN "%.0f" ${MLEN:0:${#MLEN}-3}.${MLEN:${#MLEN}-3}
HLEN=000$((650*RAY))
printf -v HLEN "%.0f" ${HLEN:0:${#HLEN}-3}.${HLEN:${#HLEN}-3}
declare -A ticks
for ((i=1;i<=12;i++));do
clksin $((5*(i%12))) $RAY tick
ticks[$tick]=$i
done
while :;do
[ "$NowM" ] || printf -v NowM "%(%M)T\n" -1
unset MPath
declare -A MPath
for ((i=1;i<=MLEN;i++));do
clksin ${NowM#0} $i tick
MPath[$tick]=M
done
[ "$NowH" ] || printf -v NowH "%(%H)T\n" -1
unset HPath
declare -A HPath
for ((i=1;i<=HLEN;i++));do
clksin $((5*(${NowH#0}%12))) $i tick
HPath[$tick]=H
done
printf -v NowS "%(%S)T\n" -1
clksin ${NowS#0} $SLEN STick
[ "$2" ] || echo -en \\e[H; # ANSI sequence for top left of console
for ((i=0;i<=2*RAY;i++));do
x=$((RAY-i))
sqrt $((RAY**2 - ${x#-}**2 )) y0
printf -v y0 "%.0f" $y0
for ((l=0;l<=2*RAY;l++));do
y=$((RAY-l));
sqrt $((RAY**2 - ${y#-}**2 )) x0
printf -v x0 "%.0f" $x0
if [ "$i $l" = "$STick" ] ;then
echo -en \\e[1ms\ \\e[0m
elif [ "${MPath["$i $l"]}" ] ;then
echo -en \\e[1m${MPath["$i $l"]}\ \\e[0m
elif [ "${HPath["$i $l"]}" ] ;then
echo -en \\e[1m${HPath["$i $l"]}\ \\e[0m
elif [ "${ticks["$i $l"]}" ] ;then
printf "%-2s" ${ticks["$i $l"]}
elif [ ${x#-} -eq $x0 ] || [ ${y#-} -eq $y0 ] ;then
echo -n .\
else
echo -n \ \
fi
done
echo -e \\e[K
done
echo -en \\e[J
[ "$2" ] && break # Exit if at least Hour was specified
printf -v SleepS "%(%s)T" -1
printf -v SleepS "%(%T)T" $((1+SleepS))
sleepUntilHires $SleepS
unset NowH NowM
done
Version plus obscurcie (2702 octets):
Comme demandé par @manatwork , il existe un version plus golfique .
Cette version est colorisée et présente l'heure numérique sur les coins.
#!/bin/bash
W=/proc;J=${1:-12} B=$2 A=$3 LANG=C R=$W/timer_list;if [ -f $R ];then Q=10
mapfile <$R e;for ((P=0;P<${#e[@]};P++));do ((Q+=${#e[P]}));[[ ${e[P]} =~ ^now
]]&&U=$Q;[[ ${e[P]} =~ offset:.*[1-9] ]]&&a=${e[P]//[a-z.: ]}&&break;done;c(){
local q p;read -N$U q <$R;q=${q%% nse*};q=$[${q##* }+a];p=$[2000000000-10#${q:
${#q}-9}];read -t .${p:1} M;};else c(){ local H;read -d\ H < $W/upti*;H=$[200
-10#${H#*.}];read -t .${H:1} M;};fi;u(){ local E=({6,2}00000) F=${E[$1&1]} G=1
while [ $G -ne $F ];do G=$F;[ $G -eq 0 ]&&F=0000||printf -v F "%u" $(((${G}000
+${1}00000000000/${G})/2));printf -v F "%.0f" ${F:0:${#F}-3}.${F:${#F}-3};done
F=0000$F;printf -v $2 "%.3f" ${F:0:${#F}-4}.${F:${#F}-4};};g(){ local t=($[7#0
] 104528 207912 309017 406737 500000 587785 669131 743145 809017 866025 913545
951057 978148 994522 1000000) j=1 x=$1 h=-1 y=$1;[ $x -gt 30 ]&&j=-1 x=$[60-x]
((x>15))&&x=$[30-x];x=00000$[J*1000000+j*${2:-10}*${t[$x]}];((y>30))&&y=$[60-y
];((y>15))&&h=1 y=$[30-y];y=00000$[J*1000000+h*${2:-10}*${t[15-y]}];printf -v\
$3 "%.0f %.0f" ${y:0:${#y}-6}.${y:${#y}-6} ${x:0:${#x}-6}.${x:${#x}-6};};v=000
v+=$((870 *J));printf -v v "%.0f" ${v:0:${#v}-3}.${v:${#v}-3};C=000$((780*J));
printf -v C "%.0f" ${C:0:${#C}-3}.${C:${#C}-3};D=000$[650*J];printf -v D %.f \
${D:0:${#D}-3}.${D:${#D}-3};declare -A m;for ((i=1;i<=12;i++));do g $[5*(i%12)
] $J w;m[$w]=$i;done;printf -v T "\e[1m%s\e[0m " . + \* o O;T=(${T});m["${J: \
} $J"]=${T} ;printf "\e[?25l\e[H\e[J";trap "printf '\e[?12l\e[?25h\e[$((2*J +3
))H\e[J';exit" 0 1 2 3 6 9 15; printf -v S "\\e[1;%dH%%(%%H)T\\e[%dH%%(%%M${Z:
})T\\e[%d;%dH%%(%%S)T" $[4*J] $[2*J+1] $[2*J+1] $[4*J];declare -A V;V["$[2 * J
] $[2*$J]"]=" ";while :;do [ "$A" ]||printf -v A "%(%M)T" -1;unset r;declare\
-A r;for ((i=1;i<=C;i++));do g ${A#0} $i w;r[$w]=M;done;[ "$B" ]||printf -v \
B "%(%H)T" -1;unset s;declare -A s;for ((i=1;i<=D;i++));do g $((5*( ${B#0}%12)
)) $i w;s[$w]=H;done;printf -v z "%(%S)T" -1;g ${z#0} $v n;[ "$2" ]||echo -en\
\\e[H;for ((i=0;i<=2*J;i++));do x=$[J-i];u $[J*J-${x#-}**2] N;printf -v N${Z:
} %.f $N;for ((l=0;l<=2*J;l++));do y=$[J-l];u $[J*J-${y#-}**2] O;printf -v O \
%.f $O;c=" ";if [ "$i $l" = "$n" ];then c=$'\e[36;1ms \e[m';elif [ "${r["${i:
} $l"]}" ] ;then c=$'\e[32;1m'${r["$i $l"]}$' \e[0m';elif [ "${s["$i $l"]}" ];
then c=$'\e[34;1m'${s["$i $l"]}$' \e[0m';elif [ "${m["$i $l"]}" ];then printf\
-v c "%-2s" "${m["$i $l"]}";elif [ ${x#-} -eq $O ] || [ ${y#-} -eq $N ] ;then
c=.\ ;else c=" ";fi;[ "$c" != "${V["$i $l"]}" ]&& V["$i $l"]="$c" && printf \
"\e[%s;%sH%-2s" $((1+i)) $[1+l*2] "$c";done;done;[ "$2" ] &&break;printf "${Z:
}\e[H\e[7mS\e[0m";c;printf "\e[H $S" -1 -1 -1;m["$J $J"]=${T[$[10#$z%${#T[@]}]
]};unset B A;done
Remarque: ne l'utilisez pas de toute façon!
Comme c'est un programme bash et que bash n'est pas un langage de programmation, ce n'est pas bien à utiliser pendant un certain temps.
Il y a une petite démo de consommation de mémoire en seulement 5 heures, avec un dessin de rayon de 7 caractères:
$ ascii-clock.sh 7
After PMem PCpu Mem
0'30" 0.0% 21.6% 12.98M
10'30" 1.0% 20.9% 48.91M
1h 0'30" 5.6% 20.8% 228.63M
2h 0'31" 11.2% 20.8% 444.25M
3h 0'32" 16.8% 20.8% 659.91M
5h 0'00" 27.9% 20.8% 1.064G
Le principal avantage de cela, c'est que lorsque j'ai besoin de mémoire, je n'ai qu'à tuer l'horloge.
( Nota: j'ai fusionné ceci, la version perl et une version javascript de celle-ci sur ascii-clock pour les geeks ;-)