У меня есть простое echo
распечатайте это, я добавил к моему .bashrc
:
echo "$(tput setaf 2)Wake up....."
sleep 2s
reset
sleep 2s
echo "$(tput setaf 2)Wake up....."
sleep 2s
reset
echo "$(tput setaf 2)Wake up neo....."
sleep 2s
echo "$(tput setaf 2)The Matrix has you......"
sleep 2s
reset
echo "$(tput setaf 2)Follow the white rabbit......"
sleep 2s
reset
cmatrix
Это печатает сообщение к терминалу, но я хочу его, смотрят, как будто он вводится с последовательной задержкой между символами.
Это не работает с Уэйлендом; если Вы используете Ubuntu 17.10 и не изменились на использование Xorg при входе в систему, это решение не для Вас.
Можно использовать xdotool
для этого. Если задержка между нажатиями клавиш должна быть последовательной, это настолько просто:
xdotool type --delay 100 something
Это вводит something
с задержкой 100
миллисекунды между каждым нажатием клавиши.
Если задержка между нажатиями клавиш должна быть случайной, скажем, от 100 до 300 миллисекунд, вещи становятся немного более сложными:
$ text="some text"
for ((i=0;i<${#text};i++));
do
if [[ "${text:i:1}" == " " ]];
then
echo -n "key space";
else
echo -n "key ${text:i:1}";
fi;
[[ $i < $((${#text}-1)) ]] && echo -n " sleep 0.$(((RANDOM%3)+1)) ";
done | xdotool -
Это for
цикл проходит каждую букву строки, сохраненной в переменной text
, печать также key <letter>
или key space
в случае пространства, сопровождаемого sleep 0.
и случайное число между 1 и 3 (xdotool
sleep
интерпретирует число как секунды). Целый вывод цикла затем передается по каналу к xdotool
, который печатает буквы со случайной промежуточной задержкой. Если Вы хотите измениться, задержка просто изменяются (RANDOM%x)+y
часть, y
будучи ниже и x-1+y
верхний предел – для 0,2 к 0,5 секундам это было бы (RANDOM%4)+2
.
Обратите внимание, что этот подход не печатает текст, а скорее вводит его точно как пользователь, сделал бы, синтезировав единственные нажатия клавиш. В последствии текст вводится в в настоящее время фокусируемое окно; если Вы изменитесь, то часть фокуса текста будет введена в недавно сфокусированном окне, которое может или не может быть тем, что Вы хотите. В любом случае взглянули на другие ответы здесь, все из которых являются блестящими!
Я попробовал xdotool после чтения ответа @dessert, но не мог заставить это работать по некоторым причинам. Таким образом, я придумал это:
while read line
do
grep -o . <<<$line | while read a
do
sleep 0.1
echo -n "${a:- }"
done
echo
done
Передайте свой текст по каналу в вышеупомянутый код, и он будет распечатан как введенный. Можно также добавить случайность путем замены sleep 0.1
с sleep 0.$((RANDOM%3))
.
Эта версия представит поддельную опечатку время от времени и исправит ее:
while read line
do
# split single characters into lines
grep -o . <<<$line | while read a
do
# short random delay between keystrokes
sleep 0.$((RANDOM%3))
# make fake typo every 30th keystroke
if [[ $((RANDOM%30)) == 1 ]]
then
# print random character between a-z
printf "\\$(printf %o "$((RANDOM%26+97))")"
# wait a bit and delete it again
sleep 0.5; echo -ne '\b'; sleep 0.2
fi
# output a space, or $a if it is not null
echo -n "${a:- }"
done
echo
done
Вы упоминаете последовательную задержку между символами, но если Вы действительно захотите, чтобы она была похожа на то, что это было введенным, то синхронизация не будет совершенно последовательна. Для достижения этого, можно записать собственный ввод с script
управляйте и воспроизведите его с scriptreplay
:
$ script -t -c "sed d" script.out 2> script.timing
Script started, file is script.out
Wake up ...
Wake up ...
Wake up Neo ...
Script done, file is script.out
$
$ scriptreplay script.timing script.out
Wake up ...
Wake up ...
Wake up Neo ...
$
Запись останавливается путем удара CTRL-D.
Передача -t
параметр к script
сообщает, что это также генерирует информацию синхронизации, которую я перенаправил к script.timing
файл. Я передал sed d
как команда к script
поскольку это - просто способ поглотить вход (и эта запись нажатия клавиш) без побочных эффектов.
Если Вы хотите сделать весь tput
/reset
наполните также, Вы могли бы хотеть сделать a script
запись для каждой из Ваших строк, и воспроизводит их, чередованный с tput
/reset
команды.
Другая возможность использует Демонстрационное Волшебство, или, чтобы быть более точной просто функция печати этого набора сценария, который в основном составляет
#!/bin/bash
. ./demo-magic.sh -w2
p "this will look as if typed"
Под капотом это использует объем плазмы, который, конечно, можно также использовать для прямого получения желаемого эффекта, взгляды канонической формы следующим образом:
echo "this will look as if typed" | pv -qL 20
В соответствии с моим псевдонимом я могу предложить другое решение:
echo "something" |
perl \
-MTime::HiRes=usleep \
-F'' \
-e 'BEGIN {$|=1} for (@F) { print; usleep(100_000+rand(200_000)) }'
Выглядит странным, не так ли?
-MTime::HiRes=usleep
импортирует функцию usleep
(сон микросекунды) от Time::HiRes
модуль, потому что обычное sleep
принимает только целочисленные секунды.-F''
разделяет данный вход на символы (разделитель, являющийся пустым ''
) и помещает символы в массив @F
.BEGIN {$|=1}
отключает вывод, буферизующий, таким образом, каждый символ является распечатанным immediatly.for (@F) { print; usleep(100_000+rand(200_000)) }
просто выполняет итерации по символам1_000
(==1000
) или даже 1_0_00
если мы считаем это легче читать.rand()
возвращает случайное число между 0 и данный аргумент, таким образом, вместе это спит между 100 000 и 299 999 микросекундами (0.1-0.3 секунды).Другой инструмент, который мог бы работать, который не зависит от x11 или что бы то ни было, является asciicinema. Это записывает все, что Вы делаете в своем терминале, и позволяет Вам воспроизвести это, как будто это был снимок экрана, только затем это - просто базирующийся ASCII! Вам, возможно, придется временно отключить Вашу подсказку однако, чтобы это было просто визуально чисто. Как другой указали, добавив, что последовательная задержка не будет выглядеть естественной, и ввод ее самостоятельно мог бы быть одним из наиболее естественного вида, которого можно достигнуть.
Записав текст, можно сделать что-то как:
$ asciinema play [your recording].cast; cmatrix
Я удивлен, что никто еще не упомянул это, но можно выполнить это с инструментами запаса и циклом:
typeit() {
local IFS=''
while read -n1 c; do
echo -n "$c"
sleep .1
done <<< "$1"
}
Это просто циклы по вводимому символу символом и распечатывает их с задержкой после каждого. Единственный хитрый бит - то, что необходимо установить IFS на пустую строку, таким образом, удар не пытается отколоться пробелы.
Это решение очень просто, настолько добавляющие переменные задержки между символами, опечатками, независимо от того, что супер легко.
РЕДАКТИРОВАНИЕ (спасибо, @dessert): Если Вы хотите немного более естественный интерфейс, Вы могли бы вместо этого сделать
typeit() {
local IFS=''
while read -n1 c; do
echo -n "$c"
sleep .1
done <<< "$@"
}
Это позволило бы Вам вызывать функцию как typeit foo bar
вместо typeit 'foo bar'
. Знайте, что без кавычек, аргументы подвергаются разделению слова удара, так например, typeit foo<space><space>bar
распечатает foo<space>bar
. Для сохранения пробела используйте кавычки.
Во-первых, "смотрят, как будто это вводится, с последовательной задержкой между символами..." немного противоречащего другому положения, как указали другие. Что-то вводимое не имеет последовательной задержки. Когда Вы будете видеть что-то произведенное с непоследовательной задержкой, Вы получите холода. "Что взято по моему компьютеру!!!??!?"
Так или иначе...
Я должен разобрать крик к expect
, который должен быть доступным на большинстве дистрибутивов Linux. Старая Школа, я знаю, но - принятие она установила - это могло едва быть более просто:
echo 'set send_human {.1 .3 1 .05 2}; send -h "The Matrix has you......\n"' | expect -f /dev/stdin
Из страницы справочника:
-h отмечают вывод сил, который будет отправлен (несколько) как человек, на самом деле вводящий. Подобные Человеку задержки появляются между символами. (Алгоритм основан на распределении Weibull с модификациями для удовлетворения этому конкретному приложению.) Этим выводом управляет значение переменной "send_human"...