J'ai un echo
simple imprimé que j'ai ajouté à mon .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
Cela affiche un message sur le terminal, mais je veux qu'il ressemble à une saisie, avec un délai constant entre les caractères.
Cela ne fonctionne pas avec Wayland; Si vous utilisez Ubuntu 17.10 et que vous n'avez pas utilisé Xorg lors de la connexion, cette solution ne vous convient pas.
Vous pouvez utiliser xdotool
pour cela. Si le délai entre les frappes doit être cohérent , c'est aussi simple que cela:
xdotool type --delay 100 something
Ceci tape something
avec un délai de 100
millisecondes entre chaque frappe.
Si le délai entre les frappes doit être aléatoire , par exemple de 100 à 300 millisecondes, les choses se compliquent un peu:
$ 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 -
Cette boucle for
parcourt chaque lettre de la chaîne enregistrée dans la variable text
et affiche key <letter>
ou key space
dans le cas d’un espace suivi de sleep 0.
et d’un nombre aléatoire compris entre 1 et 3 (xdotool
's sleep
interprète le nombre en secondes). La totalité de la sortie de la boucle est ensuite redirigée vers xdotool
, qui imprime les lettres avec le délai aléatoire entre les deux. Si vous souhaitez modifier le délai, il suffit de modifier la partie (RANDOM%x)+y
, y
étant la limite inférieure et x-1+y
la limite supérieure - pour 0,2 à 0,5 seconde, il s'agira de (RANDOM%4)+2
.
Notez que cette approche ne n'imprime pas le texte, mais le tape exactement comme le ferait l'utilisateur, en synthétisant des pressions uniques. En conséquence, le texte est tapé dans la fenêtre actuellement active. Si vous modifiez la partie active du texte, celle-ci sera saisie dans la nouvelle fenêtre, ce qui peut être différent de ce que vous voulez. Dans les deux cas, jetez un coup d’œil aux autres réponses, toutes brillantes!
J'ai essayé xdotool après avoir lu la réponse de @ dessert mais je n'ai pas réussi à le faire fonctionner pour une raison quelconque. Alors je suis venu avec ceci:
while read line
do
grep -o . <<<$line | while read a
do
sleep 0.1
echo -n "${a:- }"
done
echo
done
Introduisez votre texte dans le code ci-dessus et il sera imprimé comme dactylographié. Vous pouvez également ajouter un caractère aléatoire en remplaçant sleep 0.1
par sleep 0.$((RANDOM%3))
.
Cette version introduira une fausse typo de temps en temps et la corrigera:
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
Vous mentionnez un délai cohérent entre les caractères, mais si vous voulez vraiment que le texte soit saisi, le timing ne sera pas parfaitement cohérent. Pour ce faire, vous pouvez enregistrer votre propre frappe avec la commande script
et la lire avec scriptreplay
name__:
$ 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 ...
$
L'enregistrement est arrêté en appuyant sur CTRL-D.
Passer le paramètre -t
à script
lui indique également de générer des informations de minutage, que j'ai redirigées vers le fichier script.timing
. J'ai transmis sed d
en tant que commande à script
car il s'agit simplement d'un moyen d'absorber les entrées (et d'enregistrer les frappes au clavier) sans effets secondaires.
Si vous souhaitez également effectuer toutes les opérations tput
name __/reset
name__, vous pouvez également créer un enregistrement script
pour chacune de vos lignes et les lire, entrelacées avec les commandes tput
name__/reset
name__.
Une autre possibilité consiste à utiliser Demo Magic , ou plus précisément la fonction d'impression de cette collection de scripts, ce qui revient essentiellement à
#!/bin/bash
. ./demo-magic.sh -w2
p "this will look as if typed"
Sous le capot, cela utilise pv , que vous pouvez bien sûr aussi utiliser pour obtenir directement l'effet souhaité, la forme de base se présente comme suit:
echo "this will look as if typed" | pv -qL 20
Conformément à mon pseudo, je peux proposer une autre solution:
echo "something" |
Perl \
-MTime::HiRes=usleep \
-F'' \
-e 'BEGIN {$|=1} for (@F) { print; usleep(100_000+Rand(200_000)) }'
Ça a l'air bizarre, n'est-ce pas?
-MTime::HiRes=usleep
importe la fonction usleep
(veille microseconde) à partir du module Time::HiRes
car le nom sleep
habituel n'accepte que des secondes entières.-F''
divise l'entrée donnée en caractères (le délimiteur étant vide ''
) et place les caractères dans le tableau @F
.BEGIN {$|=1}
désactive la mise en mémoire tampon de sorte que chaque caractère soit immédiatement imprimé.for (@F) { print; usleep(100_000+Rand(200_000)) }
itère juste sur les caractères1_000
(== 1000
) ou même 1_0_00
si nous considérons que cela est plus facile à lire.Rand()
renvoie un nombre aléatoire compris entre 0 et l'argument donné. Par conséquent, la durée du sommeil est comprise entre 100 000 et 299 999 microsecondes (0,1 à 0,3 seconde).Un autre outil susceptible de fonctionner, qui ne dépend pas de x11 ni de quoi que ce soit, est asciicinema . Il enregistre tout ce que vous faites dans votre terminal et vous permet de rejouer cela comme s'il s'agissait d'une capture d'écran, mais uniquement à partir de là! Cependant, vous devrez peut-être désactiver temporairement votre invite pour qu'elle soit purement visuelle. Comme d'autres l'ont fait remarquer, l'ajout d'un délai constant ne semblera pas naturel, et le taper vous-même pourrait être l'un des aspects les plus naturels que vous puissiez obtenir.
Après avoir enregistré le texte, vous pouvez faire quelque chose comme:
$ asciinema play [your recording].cast; cmatrix
Je suis surpris que personne n'en ait encore parlé, mais vous pouvez le faire avec des outils de stock et une boucle:
typeit() {
local IFS=''
while read -n1 c; do
echo -n "$c"
sleep .1
done <<< "$1"
}
Il passe en boucle sur les caractères saisis, caractère par caractère, et les affiche avec un délai après chacun. Le seul problème est que vous devez définir votre IFS sur une chaîne vide afin que bash n'essaye pas de scinder vos espaces.
Cette solution est extrêmement simple. Vous devez donc ajouter des retards variables entre les caractères, les fautes de frappe et tout ce qui est super facile.
EDIT (merci, @dessert): Si vous voulez une interface légèrement plus naturelle, vous pouvez plutôt faire
typeit() {
local IFS=''
while read -n1 c; do
echo -n "$c"
sleep .1
done <<< "$@"
}
Cela vous permettrait d'appeler la fonction en tant que typeit foo bar
plutôt que typeit 'foo bar'
. Sachez que sans les guillemets, les arguments sont soumis au fractionnement de Word de bash. Ainsi, par exemple, typeit foo<space><space>bar
affichera foo<space>bar
. Pour conserver les espaces, utilisez des guillemets.
Premièrement, "regardez comme si c'était tapé, avec un décalage constant entre les caractères ..." est un peu contradictoire, comme d'autres l'ont souligné. Quelque chose en cours de dactylographie n'a pas un délai cohérent. Lorsque vous voyez quelque chose produit avec un délai incohérent, vous aurez des frissons. "Qu'est-ce qui a été pris sur mon ordinateur !!! ??!?"
En tous cas...
Je dois faire un appel à expect
, qui devrait être disponible sur la plupart des distributions Linux. Old School, je sais, mais si elle est installée, ce ne pourrait être plus simple:
echo 'set send_human {.1 .3 1 .05 2}; send -h "The Matrix has you......\n"' | expect -f /dev/stdin
De la page de manuel:
Le drapeau -h force la sortie à être envoyée (un peu) comme un humain en train de taper. Des délais ressemblant à des humains apparaissent entre les personnages. (L'algorithme est basé sur une distribution de Weibull, avec des modifications adaptées à cette application particulière.) Cette sortie est contrôlée par la valeur de la variable "send_human" ...