我有一份简单的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
这会将一条消息打印到终端,但我希望它看起来就像正在输入一样,并且字符之间有一致的延迟。
答案1
这不适用于 Wayland;如果您使用的是 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.
上限– 0.2 到 0.5 秒为。xdotool
sleep
xdotool
(RANDOM%x)+y
y
x-1+y
(RANDOM%4)+2
请注意,这种方法不打印文本,而是类型它与用户所做的完全一样,合成单个按键。因此,文本将被输入到当前聚焦的窗口中;如果您更改焦点,文本的一部分将被输入到新聚焦的窗口中,这可能是也可能不是您想要的。无论哪种情况,请查看此处的其他答案,它们都很棒!
答案2
在阅读@dessert的回答后,我尝试了xdotool,但由于某种原因无法使其工作。所以我想到了这个:
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
答案3
您提到字符之间有一致的延迟,但如果您真的希望它看起来像是正在输入,则时间不会完全一致。 要实现这一点,您可以使用命令录制您自己的输入,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
事情,您可能需要script
对每一行进行录音,然后播放它们,并与tput
/reset
命令交错。
答案4
根据我的昵称,我可以提供另一种解决方案:
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}
禁用输出缓冲以便立即打印每个字符。for (@F) { print; usleep(100_000+rand(200_000)) }
只是迭代字符- 在数字中添加下划线是 Perl 中使用千位分隔符的常见方式。Perl 会忽略它们,因此我们可以写
1_000
(==1000
),或者即使1_0_00
我们认为这样更容易阅读。 rand()
返回 0 和给定参数之间的一个随机数,因此总共休眠 100,000 到 299,999 微秒(0.1-0.3 秒)。