Только на 100% чистый удар ! Без вилки!
Доработанную и обновленную версию можно найти там или на этой странице:
ascii-часы для гиков . Но не используйте это! Прочитайте примечание в конце этого ответа, вы были предупреждены! Вместо этого используйте эту версию Perl !
Первые простые часы без второго тика.
Масштабируемый и редактируемый:
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
Нарисуйте часы 21x21 (10x2 + 1) в 10H10 менее чем за одну секунду.
Это принимает 3 аргумента: Usage: ascii-clock.sh [ray of clock] [Hour] [Min]
где луч по умолчанию 12, рисование часов2 x ray + 1
высота линий и двойная ширина из-за добавленного пространства, чтобы попытаться получить круглую форму.
Если скрипт вызывается с аргументом 0
или 1
, он будет циклически перерисовываться каждую минуту. Иначе, если указан хотя бы час (второй параметр), он будет рисовать только один раз и выходить.
H
Маркер находится на уровне 70% от луча и M
маркер находится на уровне 90% от луча.
Не используйте внешние двоичные файлы, такие как date
илиbc
для розыгрыша!
(Спасибо @manatwork за встроенный read -t
на месте, если/bin/sleep
).
Так что все это сделано встроенным команд оболочки.
Используется последовательность ANSI , но только для цикла и для выделения жирным шрифтом маркеров.
#!/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
Это может быть выполнено как:
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
Это будет производить что-то вроде:
+- 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 . . |
+- - - - - - - - - - - + - - - - - - - - - - - + - - - - - - - - - - - +
Или может быть запущен как:
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" &
Альтернатива: с полным рисованием пути:
#!/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
может произвести:
+- 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 . . |
+- - - - - - - - - - - + - - - - - - - - - - - + - - - - - - - - - - - +
или
. . . . 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 . . . .
В последней версии с Seconds отмечен рендеринг и наносон для синхронизации.
Это работает только в последних версиях Linux, так как используется /proc/timer_list
для подсчета доли секунды для сна между каждым обновлением.
#!/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
Более запутанная версия (2702 байта):
В соответствии с просьбой @manatwork , существует более гольф- версия.
Эта версия раскрашена и представляет цифровое время по углам.
#!/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
Примечание: не используйте это в любом случае!
Как это bash программа а bash не является языком программирования, некоторое время ее не очень удобно использовать.
Небольшая демонстрация потребления памяти всего за 5 часов с рисованием луча длиной 7 символов:
$ 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
Главное преимущество в том, что когда мне нужна память, мне просто нужно убить часы.
( Примечание: я объединил это, версию perl и одну и ту же версию javascript на ascii-clock for geeks ;-)