0

I want to do the following in bash: I have a textfile, and want to call a script that reads the file, waits for keystrokes from me and each time a correct button is pressed, it prints exactly one word (the next word) from the textfile.

To elaborate: Let's just say the textfile looks like the following

This is my
text file

and I am looking for keyboard buttons of the group [[:print:]]. So I call my script like ./script.sh textfile, then I press "A" and the Thisappears, then I press the Space button, still only the This, then I type "O" and the is appears, I press maybe "M" a few more times, until all of the text above is printed, and I'm done.

What I already have:

I already know how to wait for a single keypress and then do something if it works:

while true; do
  read -rsn1 input
    if [[ "$input" =~ "[[:print]]" ]]; then
     # do stuff on keypress
    fi
done

I also know how to read a file word by word: Read File word by word (I used answer of user Lambert)  The combination of the two does not seem to work how I want it though. 

If anyone has any idea on how to do this, I'd greatly appreciate it. Also, please remark if I did formulate anything unclear/wrong or if I asked in the wrong place/manner.

Edit for clarification The Textfile may contain an arbitrary number of lines. Each keypress should print words exactly like it stands in the Textfile, i.e. it conserves spaces and newlines (think of the script I want to achieve as a delayed cat that prints not the whole file at once, but only Word by Word on keystroke)

  • Is that just one line in textfile, or can there be more than one? – RudiC Oct 11 '18 at 8:01
  • in regards to the keys you're pressing, I see no connection between them. Can you clarify if you're expecting any alpha-numeric keystroke to print the next word? – RobotJohnny Oct 11 '18 at 8:01
  • @RudiC Yes, Textfile may contain an arbitrary number of lines. – Pharguin Oct 11 '18 at 8:08
  • @RobotJohnny Sorry if I did not make it clear. I am expecting any alpha-numeric keystroke, i.e. a-z A-Z 0-9. – Pharguin Oct 11 '18 at 8:09
0

You're not too far off for a one line file. Try arrays and get rid of your syntax errors:

read -a TMPARR < file
while read -n1 CH && [[ $CNT -lt ${#TMPARR[@]} ]]; do [[ "$CH" =~ [[:print:]] ]] && echo ${TMPARR[((CNT++))]}; done

For a multiline file, try

while read -a TMPARR <&3
   do   CNT=0
        [[ $CNT -lt ${#TMPARR[@]} ]] && read -sn1 CH
        while read -sn1 CH && [[ $CNT -lt ${#TMPARR[@]} ]]
          do [[ "$CH" =~ [[:print:]] ]] && echo ${TMPARR[((CNT++))]}
          done
   done  3< file

You have to split the input file descriptors for reading the text lines sequentially and reading from the terminal in parallel.

  • How could I modify this so this works for multiple lines? I added a short clarification to my question on how I want the output to look, too. – Pharguin Oct 11 '18 at 8:31
  • Thanks for your Input so far. This almost does the trick. It still prints every word seperate on a new line. If I use echo -n "${TMPARR[((CNT++))]} " I get the text separated by spaces. Still, all newlines from the original file are omitted (I am guessing because of how the Array gets created?). I want to keep the formatting exactly like in the original file though, so with all linebreaks, spaces, identations etc intact, if possible. – Pharguin Oct 11 '18 at 9:58
  • Would adding an echo between the two dones help? – RudiC Oct 11 '18 at 10:26
  • This does the trick! Thanks and accepted. – Pharguin Oct 11 '18 at 10:53

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.