टर्मिनल में टेक्स्ट कैसे प्रिंट करें जैसे कि वह टाइप किया जा रहा है?


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
यथार्थवादी होने के लिए मुझे लगता है कि आपके पास सही करने के लिए एक या एक से अधिक बैक स्पेस के साथ रैंडम टाइपो होना चाहिए। उदाहरण के लिए इस टिप्पणी को टाइप करते समय मुझे "थ्रो" करने के लिए इसे सही करने के लिए "के माध्यम से" पर वापस अंतरिक्ष में जाना पड़ा। यह उत्तर देने के लिए अधिक कठिन प्रश्न बनाता है लेकिन यह इसे अधिक यथार्थवादी बनाता है। यदि पात्र 30 CPS या 60 CPS की स्थिर गति से दोहराते हैं तो यह कम मानव दिखता है। कुछ कुंजी एक साथ तेजी से टाइप की जाती हैं, जबकि अन्य कुंजी संयोजन धीमा दिखाई देते हैं। गति के लिए कुंजी संयोजनों के मिलान के कुछ प्रकार की आवश्यकता होती है।
विनयुनुच्स

2
@ WinEunuuchs2Unix मुझे नहीं लगता कि यह अभी भी सिम्प्लाइज्ड है। ;)
मिठाई

जवाबों:


28

यह वायलैंड के साथ काम नहीं करता है; यदि आप Ubuntu 17.10 का उपयोग कर रहे हैं और लॉगिन पर Xorg का उपयोग करने के लिए नहीं बदला है, तो यह समाधान आपके लिए नहीं है।

आप उसके xdotool 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.और 1 और 3 के बीच एक यादृच्छिक संख्या ( xdotoolकी sleepव्याख्या सेकंड के रूप में संख्या)। लूप के पूरे आउटपुट को तब पाइप किया जाता है xdotool, जो अक्षरों को बीच में यादृच्छिक देरी से प्रिंट करता है। यदि आप देरी को बदलना चाहते हैं तो बस भाग को बदल दें , निचली और ऊपरी सीमा - 0.2 से 0.5 सेकंड के लिए ।(RANDOM%x)+yyx-1+y(RANDOM%4)+2

ध्यान दें कि यह दृष्टिकोण पाठ को प्रिंट नहीं करता है , बल्कि इसे ठीक उसी तरह टाइप करता है जैसे उपयोगकर्ता सिंगल कीपेस को संश्लेषित करता है। परिणाम में पाठ वर्तमान में केंद्रित विंडो में टाइप हो जाता है; यदि आप बदलते हैं तो पाठ का फोकस भाग नई केंद्रित विंडो में टाइप हो जाएगा, जो आप चाहते हैं या नहीं हो सकता है। या तो मामले में यहाँ अन्य उत्तरों पर एक नज़र है, जो सभी शानदार हैं!


24

मैंने @ डेज़र्ट के उत्तर को पढ़ने के बाद 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 -rऔर printf "%s"यह सुनिश्चित करें कि खाली स्थान के और विशेष वर्ण किसी भी अलग तरह से व्यवहार नहीं कर रहे हैं। और grepवर्णों में विभाजित करने के लिए प्रत्येक पंक्ति पर अनावश्यक है - बस forपंक्ति में प्रत्येक चार पर एक लूप पर्याप्त है।
डिजिटल ट्रामा

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

एक अन्य संभावना डेमो मैजिक का उपयोग कर रही है , या, इस स्क्रिप्ट संग्रह के प्रिंट फ़ंक्शन को और अधिक सटीक बनाने के लिए, जो मूल रूप से होती है

#!/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 का यह उपयोग बहुत अच्छा है।
सेबेस्टियन स्टार्क

3
पाइप echoकरने की आवश्यकता नहीं है 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::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 सेकंड) के बीच सोता है।

जिज्ञासा से बाहर: क्या rand()0 से तर्क में एक संख्या लौटाता है (आपके उदाहरण में 100 k से 300k) या उनके बीच (100k + 1 से 300k-1 आपके उदाहरण में)?
मिठाई

1
यह अंतराल में एक संख्या देता है [0,200k), अर्थात 0 सहित लेकिन 200k को छोड़कर। सटीक व्यवहार यहाँ प्रलेखित किया गया है : "0 से अधिक या बराबर एक यादृच्छिक भिन्न संख्या लौटाता है और EXPR के मान से कम है। (EXPR सकारात्मक होना चाहिए।)"
PerlDuck

1
यह बिना -a और -n
rrauenza

Perl 5.20 के बाद से @rrauenza करता है। -Fतात्पर्य -aऔर -aअर्थ -n
पर्लडक

आह, ठीक है मैं 5.16 का उपयोग कर रहा था, जो कि CentOS7 पर है।
रौज़ेना

6

एक और उपकरण जो काम कर सकता है, जो x11 या जो कुछ भी निर्भर नहीं करता है, वह है एसिसीकिनिमा । यह आपके टर्मिनल में सब कुछ रिकॉर्ड करता है और आपको फिर से लिखने देता है जैसे कि यह एक स्क्रीन कैप्चर था, तभी यह पूरी तरह से एएससीआई आधारित है! आपको अपने प्रॉम्प्ट को अस्थायी रूप से अक्षम करना पड़ सकता है लेकिन इसके लिए विशुद्ध रूप से नेत्रहीन होना चाहिए। जैसा कि अन्य ने बताया है, एक सुसंगत देरी जोड़ना स्वाभाविक नहीं लगेगा, और इसे टाइप करना आपके लिए सबसे स्वाभाविक रूप से एक हो सकता है जिसे आप प्राप्त कर सकते हैं।

पाठ रिकॉर्ड होने के बाद, आप कुछ ऐसा कर सकते हैं:

$ asciinema play [your recording].cast; cmatrix

6

मुझे आश्चर्य है कि किसी ने अभी तक इसका उल्लेख नहीं किया है, लेकिन आप इसे स्टॉक टूल और लूप के साथ पूरा कर सकते हैं:

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

यह सिर्फ चरित्र द्वारा इनपुट चरित्र पर लूप करता है और प्रत्येक के बाद देरी के साथ उन्हें प्रिंट करता है। केवल मुश्किल सा यह है कि आपको अपने IFS को एक खाली स्ट्रिंग पर सेट करना होगा ताकि bash आपके रिक्त स्थान को विभाजित करने का प्रयास न करे।

यह समाधान मृत-सरल है, इसलिए वर्ण, टाइपो, जो भी सुपर आसान है, के बीच परिवर्तनशील देरी को जोड़ना।

EDIT (धन्यवाद, @ डेज़र्ट): यदि आप थोड़ा अधिक प्राकृतिक इंटरफ़ेस चाहते हैं, तो आप इसके बजाय कर सकते हैं

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

यह आपको फ़ंक्शन को कॉल करने की typeit foo barबजाय अनुमति देगा typeit 'foo bar'। विदित हो कि उद्धरणों के बिना, तर्क शब्द के विभाजन के अधीन होते हैं, इसलिए उदाहरण के लिए typeit foo<space><space>barप्रिंट होगा 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करनी है, जो कि अधिकांश लिनक्स वितरण पर उपलब्ध होनी चाहिए। पुराने स्कूल, मुझे पता है, लेकिन यह मानते हुए कि यह स्थापित है - यह शायद ही सरल हो सकता है:

echo 'set send_human {.1 .3 1 .05 2}; send -h "The Matrix has you......\n"' | expect -f /dev/stdin

आदमी पृष्ठ से:

-H झंडा बल उत्पादन (कुछ) एक मानव वास्तव में टाइपिंग की तरह भेजा जाना है। पात्रों के बीच मानव जैसी देरी दिखाई देती है। (एल्गोरिथ्म एक वीबुल वितरण पर आधारित है, जिसमें इस विशेष एप्लिकेशन के अनुरूप संशोधन किए गए हैं।) इस आउटपुट को चर "send_human" के मान से नियंत्रित किया जाता है ...

Https://www.tcl.tk/man/expect5.31/expect.1.html देखें

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.