Tenho uma echo
impressão simples que adicionei ao meu .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
Isso imprime uma mensagem no terminal, mas quero que pareça estar sendo digitada, com um atraso consistente entre os caracteres.
command-line
bash
echo
SimplySimplified
fonte
fonte
Respostas:
Isso não funciona com Wayland; se você está usando o Ubuntu 17.10 e não mudou para o Xorg no login, esta solução não é para você.
Você pode usar
xdotool
para isso. Se o atraso entre as teclas for consistente , é simples assim:Isso digita
something
com um atraso de100
milissegundos entre cada pressionamento de tecla.Se o atraso entre as teclas for aleatório , digamos de 100 a 300 milissegundos, as coisas ficam um pouco mais complicadas:
Esse
for
loop percorre todas as letras da sequência salva na variáveltext
, imprimindo umkey <letter>
oukey space
no caso de um espaço seguido porsleep 0.
e um número aleatório entre 1 e 3 (xdotool
'ssleep
interpreta o número como segundos). Toda a saída do loop é então canalizadaxdotool
, o que imprime as letras com o atraso aleatório no meio. Se você quiser alterar o atraso, basta alterar a parte, sendo o limite inferior e superior - por 0,2 a 0,5 segundos .(RANDOM%x)+y
y
x-1+y
(RANDOM%4)+2
Observe que essa abordagem não imprime o texto, mas digite -o exatamente como o usuário faria, sintetizando pressionamentos de tecla únicos. Em conseqüência, o texto é digitado na janela atualmente focada; se você alterar a parte do foco, o texto será digitado na janela recém-focada, que pode ou não ser o que você deseja. Em ambos os casos, dê uma olhada nas outras respostas aqui, todas brilhantes!
fonte
Tentei o xdotool depois de ler a resposta da @ dessert, mas não consegui fazê-lo funcionar por algum motivo. Então, eu vim com isso:
Canalize seu texto no código acima e ele será impresso como digitado. Você também pode adicionar aleatoriedade substituindo
sleep 0.1
porsleep 0.$((RANDOM%3))
.Versão estendida com erros de digitação
Esta versão apresentará um erro de digitação de vez em quando e a corrigirá:
fonte
while IFS= read -r line; do for (( i = 0; i < ${#line}; i++ )); do sleep 0.1; printf "%s" "${line:i:1}"; done; echo; done
(substitua;
por novas linhas e recuo conforme necessário). OIFS= read -r
eprintf "%s"
garantir que espaços em branco e caracteres especiais não são tratados de forma diferente. E ogrep
em cada linha para dividir em caracteres é desnecessário - apenas umfor
loop sobre cada caractere na linha é suficiente.Você menciona um atraso consistente entre os caracteres, mas se realmente deseja que ele seja digitado, o tempo não será perfeitamente consistente. Para conseguir isso, você pode gravar sua própria digitação com o
script
comando e reproduzi-lo comscriptreplay
:A gravação é interrompida pressionando CTRL-D.
Passar o
-t
parâmetro para asscript
instruções também gera informações de tempo, que eu redirecionei para oscript.timing
arquivo. Eu passeised d
como um comando para,script
pois essa é simplesmente uma maneira de absorver a entrada (e isso registra as teclas digitadas) sem efeitos colaterais.Se você quiser fazer todas as coisas
tput
/reset
também, poderá fazer umascript
gravação para cada uma das suas linhas e reproduzi-las, intercaladas com os comandostput
/reset
.fonte
Outra possibilidade é usar o Demo Magic ou, para ser mais preciso, apenas a função de impressão dessa coleção de scripts, que basicamente equivale a
Sob o capô, isso usa o pv , que obviamente você também pode usar para obter diretamente o efeito desejado, a forma básica é a seguinte:
fonte
echo
parapv
, basta usarpv -qL20 <<< "Hello world"
se seus apoios shell herestrings.De acordo com meu apelido, posso oferecer outra solução:
Parece estranho, não é?
-MTime::HiRes=usleep
importa a funçãousleep
(suspensão de microssegundos) doTime::HiRes
módulo porque o habitualsleep
aceita apenas segundos inteiros.-F''
divide a entrada fornecida em caracteres (o delimitador está vazio''
) e coloca os caracteres na matriz@F
.BEGIN {$|=1}
desativa o buffer de saída para que cada caractere seja impresso imediatamente.for (@F) { print; usleep(100_000+rand(200_000)) }
apenas itera sobre os caracteres1_000
(==1000
) ou mesmo1_0_00
se considerarmos mais fácil de ler.rand()
retorna um número aleatório entre 0 e o argumento fornecido, portanto, juntos, eles dormem entre 100.000 e 299.999 microssegundos (0,1-0,3 segundos).fonte
rand()
retorna um número de 0 ao argumento (100k a 300k no seu exemplo) ou entre eles (100k + 1 a 300k-1 no seu exemplo)?[0,200k)
, ou seja, inclui 0, mas exclui 200k. O comportamento exato é documentado aqui : "retorna um número fracionário aleatório maior ou igual a 0 e menor do que o valor de expr (expr deve ser positivo.)."-F
implica-a
e-a
implica-n
.Outra ferramenta que pode funcionar, que não depende de x11 ou o que seja, é o asciicinema . Ele grava tudo o que você faz no seu terminal e permite que você repita isso como se fosse uma captura de tela, só então é puramente baseada em ASCII! No entanto, talvez seja necessário desativar temporariamente o prompt para que ele seja visualmente limpo. Como outros já apontaram, adicionar um atraso consistente não parecerá natural, e digitar você mesmo pode ser um dos olhares mais naturais que você pode obter.
Depois de gravar o texto, você pode fazer algo como:
fonte
Estou surpreso que ninguém tenha mencionado isso ainda, mas você pode fazer isso com ferramentas de estoque e um loop:
Ele apenas circula o caractere de entrada por caractere e os imprime com um atraso após cada um. A única parte complicada é que você deve definir seu IFS como uma string vazia para que o bash não tente separar seus espaços.
Essa solução é simples, adicionando atrasos variáveis entre caracteres, erros de digitação, o que for super fácil.
EDIT (obrigado, @dessert): se você quiser uma interface um pouco mais natural, poderá fazer
Isso permitiria que você chamasse a função em
typeit foo bar
vez detypeit 'foo bar'
. Esteja ciente de que, sem aspas, os argumentos estão sujeitos à divisão de palavras do bash; portanto, por exemplo,typeit foo<space><space>bar
serão impressosfoo<space>bar
. Para preservar espaços em branco, use aspas.fonte
typeit foo<space>bar
irá resultar emfoo bar
, ao passo quetypeit foo<space><space>bar
irá também resultar emfoo bar
. Você precisa citá-lo para garantir que seja literal. @dessert fique à vontade para sugerir uma edição. Eu posso fazer isso sozinho, mas quero lhe dar a chance de obter crédito por isso.read -n1
(o que, aliás, estáread -k1
em zsh) #Primeiro, "parece que está sendo digitado, com um atraso consistente entre os caracteres ..." é um pouco contraditório, como outros já apontaram. Algo sendo digitado não tem um atraso consistente. Quando você vê algo produzido com um atraso inconsistente, fica arrepiado. "O que tomou conta do meu computador !!! ??!?"
De qualquer forma...
Eu tenho que gritar
expect
, o que deve estar disponível na maioria das distribuições Linux. A Old School, eu sei, mas, desde que esteja instalada, dificilmente poderia ser mais simples:Na página do manual:
Consulte https://www.tcl.tk/man/expect5.31/expect.1.html
fonte