입력하는 것처럼 터미널에 텍스트를 인쇄하는 방법은 무엇입니까?


27

내가 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
현실적으로 하나 이상의 백 스페이스로 임의의 오타가 발생하여 수정해야한다고 생각합니다. 예를 들어,이 주석을 입력하는 동안 "throw"에 대한 공백을 "throw"로 수정해야했습니다. 대답하기가 더 어려운 질문이지만 더 현실적으로 만듭니다. 캐릭터가 30 CPS 또는 60 CPS의 꾸준한 속도로 반복되면 사람이 덜 보입니다. 특정 키는 더 빨리 입력되는 반면 다른 키 조합은 느리게 나타납니다. 키 조합과 속도의 패턴 일치가 필요합니다.
WinEunuuchs2Unix

2
@ WinEunuuchs2Unix 나는 이것이 여전히 SimplySimplified라고 생각하지 않습니다. ;)
디저트

답변:


28

Wayland에서는 작동하지 않습니다. Ubuntu 17.10을 사용 중이고 로그인시 Xorg를 사용하도록 변경하지 않은 경우이 솔루션은 적합하지 않습니다.

사용할 수 있습니다 xdotool xdotool 설치. 키 스트로크 사이의 지연 시간이 일정 해야한다면 다음 과 같이 간단합니다.

xdotool type --delay 100 something

각 키 스트로크 사이 something100밀리 초의 지연 이있는 유형 입니다 .


키 스트로크 사이의 지연 시간이 무작위 라면 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 사이의 난수 ( xdotoolsleep해석 초로 수). 그런 다음 루프의 전체 출력이로 파이프 xdotool되어 사이에 임의 지연이있는 문자를 인쇄합니다. 지연을 변경하려면 0.2 ~ 0.5 초 동안 하한 과 상한 인 부품 만 변경하면 됩니다.(RANDOM%x)+yyx-1+y(RANDOM%4)+2

이 방법은 텍스트를 인쇄 하지 않고 단일 키 누르기를 합성하여 사용자가 입력 한 것과 똑같이 입력 합니다. 결과적으로 텍스트는 현재 포커스 된 창에 입력됩니다. 포커스를 변경하면 텍스트의 일부가 새로 포커스 된 창에 입력되며, 원하는 위치에있을 수도 있고 아닐 수도 있습니다. 두 경우 모두 다른 답변을 살펴보십시오. 모두 훌륭합니다!


24

@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

나는 이것을 대신 할 것이라고 생각한다 : while IFS= read -r line; do for (( i = 0; i < ${#line}; i++ )); do sleep 0.1; printf "%s" "${line:i:1}"; done; echo; done( ;필요에 따라 줄 바꿈과 들여 쓰기로 대체 하십시오). IFS= read -rprintf "%s"공백 및 특수 문자가 어떤 다르게 취급되지 않도록. 그리고 grep각 줄에서 문자로 나눌 필요는 없습니다 for. 줄의 각 문자를 반복하면 충분합니다.
Digital Trauma

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 ...

$ 

CTRL-D를 누르면 기록이 중지됩니다.

-t매개 변수를 전달하면 script시간 정보도 생성되어 script.timing파일로 리디렉션 됩니다. 나는 이것이 부작용없이 입력 (및이 키 입력 기록)을 흡수하는 방법이기 때문에 sed d명령으로 전달 했습니다 script.

모든 tput/ reset작업도 수행하려면 script각 라인에 대해 녹음 을 수행 하고 tput/ reset명령 과 함께 인터리브하여 재생할 수 있습니다 .


11

또 다른 가능성은 Demo Magic을 사용 하거나이 스크립트 모음의 인쇄 기능을보다 정확하게 만드는 것입니다.

#!/bin/bash

. ./demo-magic.sh -w2

p "this will look as if typed"

후드 아래에서 이것은 pv를 사용하며 , 물론 원하는 효과를 직접 얻는 데 사용할 수도 있습니다. 기본 형식은 다음과 같습니다.

echo "this will look as if typed" | pv -qL 20

1
이 pv 사용법은 훌륭합니다.
Sebastian Stark

3
에 파이프 echo할 필요 가 없으며 쉘이 herestring을 지원 pv하는 pv -qL20 <<< "Hello world"경우 사용 하십시오.
dr01

8

내 별명에 따라 다른 솔루션을 제공 할 수 있습니다.

echo "something" | 
    perl \
        -MTime::HiRes=usleep \
        -F'' \
        -e 'BEGIN {$|=1} for (@F) { print; usleep(100_000+rand(200_000)) }'

이상하게 보입니까?

  • -MTime::HiRes=usleep평소 에는 정수 초만 허용 되므로 모듈 usleep에서 함수 (마이크로 초 절전)를 가져옵니다 .Time::HiRessleep
  • -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 초) 사이에서 휴면 상태가됩니다.

호기심에서 그냥 : rand()0에서 인수 (예 : 100k-300k ) 또는 숫자 사이 ( 예 : 100k + 1-300k-1 ) 사이 의 숫자를 반환 합니까 ?
디저트

1
간격에있는 숫자 [0,200k), 즉 0을 포함하지만 200k를 제외한 숫자를 반환합니다 . 정확한 동작은 다음과 같습니다. "0보다 크거나 같고 EXPR 값보다 작은 임의의 소수를 반환합니다 (EXPR은 양수 여야 함)"
PerlDuck

1
이 -a 및 -n이없는 것은 아니다 작업을 수행
rrauenza

@rrauenza Perl 5.20부터 . -F암시 -a하고 -a암시합니다 -n.
PerlDuck

아, 좋아, CentOS7에있는 5.16을 사용하고있었습니다.
rrauenza

6

x11이나 다른 것에 의존하지 않는 다른 도구는 asciicinema 입니다. 그것은 당신이 당신의 터미널에서하는 모든 것을 기록하고 마치 화면 캡처 인 것처럼 순전히 ASCII 기반으로 재생할 수 있습니다! 그러나 시각적으로 깨끗하게 표시하려면 프롬프트를 일시적으로 비활성화해야합니다. 다른 사람들이 지적했듯이, 일정한 지연을 추가하면 자연스럽게 보이지 않으며 직접 입력하는 것이 가장 자연스럽게 보일 수 있습니다.

텍스트를 기록한 후에는 다음과 같은 작업을 수행 할 수 있습니다.

$ asciinema play [your recording].cast; cmatrix

6

아무도 이것을 언급하지 않은 것에 놀랐지 만 스톡 툴과 루프로 이것을 달성 할 수 있습니다.

typeit() {
    local IFS=''
    while read -n1 c; do
        echo -n "$c"
        sleep .1
    done <<< "$1"
}

입력 문자를 문자별로 반복하여 각 문자마다 지연으로 인쇄합니다. 유일한 까다로운 점은 IFS를 빈 문자열로 설정해야하므로 bash가 공백을 분리하려고 시도하지 않는 것입니다.

이 솔루션은 매우 간단하기 때문에 문자, 오타 사이에 가변 지연을 추가하면 매우 쉽습니다.

편집 (감사, @dessert) : 좀 더 자연스러운 인터페이스를 원한다면 대신 할 수 있습니다

typeit() {
    local IFS=''
    while read -n1 c; do
        echo -n "$c"
        sleep .1
    done <<< "$@"
}

이를 통해 함수를 typeit foo bar대신 호출 할 수 있습니다 typeit 'foo bar'. 따옴표없이 인수는 bash의 단어 분할에 종속되므로 예를 들어 typeit foo<space><space>barprint를 인쇄 foo<space>bar합니다. 공백을 유지하려면 따옴표를 사용하십시오.


좋은 제안이지만 단어 분리가 적용된다는 점에 유의해야합니다. 예를 들어, typeit foo<space>bar발생합니다 foo bar반면 typeit foo<space><space>bar또한 초래 foo bar. 당신은 그것이 그대로 있는지 확인하기 위해 인용해야합니다. @dessert는 자유롭게 편집을 제안합니다. 나는 그것을 스스로 할 수 있지만, 당신에게 그것을 얻을 수있는 기회를주고 싶다.
whereswalden

에 대해 가르쳐 +1 read -n1(., BTW 인 read -k1zsh을에)
세바스찬 스타크

5

첫째, 다른 사람들이 지적했듯이 "문자 사이에 일관된 지연으로 입력하는 것처럼 보입니다 ..."는 약간 모순됩니다. 입력하는 내용에 일관된 지연이 없습니다. 일관되지 않은 지연으로 제작 된 것을 보면 오한이됩니다. "내 컴퓨터가 무엇을 가져 갔습니까 !!! ??!?"

어쨌든...

나는 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"의 값으로 제어됩니다.

참조 https://www.tcl.tk/man/expect5.31/expect.1.html를

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.