Sim*_*ied 26 command-line bash echo
我有一个简单的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
Run Code Online (Sandbox Code Playgroud)
这会向终端打印一条消息,但我希望它看起来像是正在键入,并且字符之间具有一致的延迟。
des*_*ert 28
这不适用于 Wayland;如果您使用的是 Ubuntu 17.10 并且在登录时未更改为使用 Xorg,则此解决方案不适合您。
您可以使用 xdotool 为了那个原因。如果击键之间的延迟应该是一致的,就这么简单:
xdotool type --delay 100 something
Run Code Online (Sandbox Code Playgroud)
这种类型在每次击键之间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 -
Run Code Online (Sandbox Code Playgroud)
这个for循环遍历保存在变量中的字符串的每个字母text,打印key <letter>或者key space在空格后跟sleep 0.一个 1 到 3 之间的随机数的情况下打印(xdotool'ssleep将数字解释为秒)。然后将循环的整个输出通过管道传送到xdotool,打印字母之间的随机延迟。如果您想更改延迟,只需更改部分,即下限和上限 – 0.2 到 0.5 秒将是。(RANDOM%x)+yyx-1+y(RANDOM%4)+2
请注意,这种方法不会打印文本,而是像用户一样输入它,合成单个按键。结果文本被输入到当前聚焦的窗口中;如果您更改焦点部分,文本将被输入到新聚焦的窗口中,这可能是您想要的,也可能不是。无论哪种情况,请查看此处的其他答案,所有答案都很棒!
Seb*_*ark 25
我在阅读@dessert 的回答后尝试了 xdotool,但由于某种原因无法让它工作。所以我想出了这个:
while read line
do
grep -o . <<<$line | while read a
do
sleep 0.1
echo -n "${a:- }"
done
echo
done
Run Code Online (Sandbox Code Playgroud)
将您的文本输入到上面的代码中,它会像打字一样打印出来。您还可以通过替换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
Run Code Online (Sandbox Code Playgroud)
Dig*_*uma 18
您提到了字符之间的一致延迟,但如果您真的希望它看起来像被键入,那么时间将不会完全一致。为此,您可以使用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 ...
$
Run Code Online (Sandbox Code Playgroud)
按 CTRL-D 停止录制。
将-t参数传递给script指示它还会生成计时信息,我已将这些信息重定向到该script.timing文件。我已将其sed d作为命令传递给,script因为这只是一种吸收输入(并记录击键)而没有副作用的方法。
如果你也想做所有的tput/reset东西,你可能想为你的script每一行录音,然后播放它们,与tput/reset命令交错。
god*_*lka 11
另一种可能性是使用Demo Magic,或者,更准确地说只是这个脚本集合的打印功能,基本上相当于
#!/bin/bash
. ./demo-magic.sh -w2
p "this will look as if typed"
Run Code Online (Sandbox Code Playgroud)
在引擎盖下,这使用pv,当然您也可以使用它来直接获得所需的效果,基本形式如下:
echo "this will look as if typed" | pv -qL 20
Run Code Online (Sandbox Code Playgroud)
根据我的昵称,我可以提供另一种解决方案:
echo "something" |
perl \
-MTime::HiRes=usleep \
-F'' \
-e 'BEGIN {$|=1} for (@F) { print; usleep(100_000+rand(200_000)) }'
Run Code Online (Sandbox Code Playgroud)
看起来很奇怪,不是吗?
-MTime::HiRes=usleepusleep从Time::HiRes模块导入函数(微秒睡眠),因为通常sleep只接受整数秒。-F''将给定的输入拆分为字符(分隔符为空'')并将字符放入数组中@F。BEGIN {$|=1} 禁用输出缓冲,以便立即打印每个字符。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 秒)之间休眠。我很惊讶还没有人提到这一点,但是您可以使用库存工具和循环来完成此操作:
typeit() {
local IFS=''
while read -n1 c; do
echo -n "$c"
sleep .1
done <<< "$1"
}
Run Code Online (Sandbox Code Playgroud)
它只是逐个字符地循环输入,并在每个字符之后延迟打印出来。唯一棘手的一点是您必须将 IFS 设置为空字符串,以便 bash 不会尝试拆分您的空间。
这个解决方案非常简单,因此在字符之间添加可变延迟、拼写错误等都非常容易。
编辑(谢谢,@dessert):如果你想要一个更自然的界面,你可以改为
typeit() {
local IFS=''
while read -n1 c; do
echo -n "$c"
sleep .1
done <<< "$@"
}
Run Code Online (Sandbox Code Playgroud)
这将允许您将函数调用为 astypeit foo bar而不是typeit 'foo bar'。请注意,如果没有引号,参数会受到 bash 的分词,因此例如typeit foo<space><space>bar将打印foo<space>bar. 要保留空格,请使用引号。
另一个可能工作的工具是asciicinema,它不依赖于 x11 或其他任何东西。它会记录您在终端中所做的一切,并让您像截屏一样重放它,只有这样它才完全基于 ASCII!您可能必须暂时禁用您的提示,但它是纯粹的视觉清洁。正如其他人指出的那样,添加一致的延迟看起来并不自然,而自己输入可能是您可以实现的最自然的外观之一。
记录文本后,您可以执行以下操作:
$ asciinema play [your recording].cast; cmatrix
Run Code Online (Sandbox Code Playgroud)
首先,正如其他人指出的那样,“看起来好像是在输入,字符之间有一致的延迟......”有点矛盾。输入的内容没有一致的延迟。当您看到延迟不一致的东西时,您会感到不寒而栗。“我的电脑被什么东西占用了!!!??!?”
反正...
我必须对 大喊大叫expect,它应该在大多数 Linux 发行版上都可用。老派,我知道,但是 - 假设它已安装 - 它几乎不可能更简单:
echo 'set send_human {.1 .3 1 .05 2}; send -h "The Matrix has you......\n"' | expect -f /dev/stdin
Run Code Online (Sandbox Code Playgroud)
从手册页:
-h 标志强制输出(有点)像人类实际打字一样发送。人物之间出现了类似人类的延迟。(该算法基于 Weibull 分布,并进行了修改以适应此特定应用。)此输出由变量“send_human”的值控制...
见https://www.tcl.tk/man/expect5.31/expect.1.html