Reading arrow keys in terminal (partial success!)

Joined
Jul 5, 2011
Messages
2
Reaction score
0
Points
1
Ok, I just picked up bash today, and after several hours got to a point where I can use what I know fluently. Realizing that I could probably use bash for a neat graphics script, I used WSAD to move a character around the screen. During the tests, I would sometimes furiously bang on the arrow keys. To my surprise, characters showed up. Upon experimentation, I discovered that the arrow keys DO get picked up by read. It has the format ^[[A. The letter at the end indicates which arrow was pressed. The first character, however, is an escape key (ASCII 27 or 0x1B). I then set about finding a way to read keyboard input one character at a time, and test for the escape key.

The main effect of the escape key in bash is that it hides the character in front of it. So, I exploited this like so:
Code:
#!/bin/bash
read -n 1 -s -p "Press the up arrow." KEY
TEST=test
if [ "$(echo $KEY$TEST)" = "est" ]; then
 read -n 1 -s GARBAGE
 read -n 1 -s KEY
 if [ "$KEY" = "A" ]; then
  echo "You pressed the UP arrow."
 fi
else
 echo "You didn't press an arrow, did you?"
fi

The code didn't work. It returned the error:
Code:
line 4: unexpected EOF while looking for matching `''

Upon further investigation, I found that $(echo $KEY$TEST) does, in fact, return "est". However, it seems to have something invisible with it, because every comparison will fail.

So, I can test for arrows, but I need to test for the escape char, and that seems to be impossible. Any suggestions?

Any and all help is greatly appreciated!
 
Joined
Jul 7, 2014
Messages
1
Reaction score
0
Points
1
Solution:
Code:
#!/bin/bash
echo "Press the UP arrow."
read -sn1 esc
read -sn1 -t 0.001 bra # "-t 0.001" is for robust-ness so pressing just any key wont put it into the wrong "read"
read -sn1 -t 0.001 typ
if [ "$esc$bra$typ" == $'\033'[A ]; then
    echo "You pressed the UP arrow."
else
    echo "You didn't press the up arrow, did you?"
fi
If you have any questions, contact me. UP=A DOWN=B RIGHT=C LEFT=D
 
Last edited:
Joined
Dec 2, 2017
Messages
1
Reaction score
0
Points
1
Solution:
Code:
#!/bin/bash
echo "Press the UP arrow."
read -sn1 esc
read -sn1 -t 0.001 bra # "-t 0.001" is for robust-ness so pressing just any key wont put it into the wrong "read"
read -sn1 -t 0.001 typ
if [ "$esc$bra$typ" == $'\033'[A ]; then
    echo "You pressed the UP arrow."
else
    echo "You didn't press the up arrow, did you?"
fi
If you have any questions, contact me. UP=A DOWN=B RIGHT=C LEFT=D
Not sure when this was changed but for anyone who found this thread ages after the original post (like me), the read command can't have a timeout of <1 second. Which means that with this solution, you would have to wait two seconds before a character was detected. Luckily, I have a fix.
Code:
#!/bin/bash
echo "Press the UP arrow."
read -rsn1 esc
if [ $esc == $'\033' ]; then
    read -sn1 bra
    read -sn1 typ
fi
if [ "$esc$bra$typ" == $'\033'[A ]; then
    echo "You pressed the UP arrow."
else
    echo "You didn't press the up arrow, did you?"
fi
 

Shop Amazon


Shop for your Apple, Mac, iPhone and other computer products on Amazon.
We are a participant in the Amazon Services LLC Associates Program, an affiliate program designed to provide a means for us to earn fees by linking to Amazon and affiliated sites.
Top