In the book Advanced Bash-Scripting Guide Section 5.2 Example 5-3. Detecting key-presses. The whole code can be viewed at detecting_key-presses.sh. In the example, there is some code snippet which I can't understand.
First snippets:
# Convert the separate home-key to home-key_num_7:
if [ "$key" = $'\x1b\x4f\x48' ]; then
key=$'\x1b\x5b\x31\x7e'
# Quoted string-expansion construct.
fi
# Convert the separate end-key to end-key_num_1.
if [ "$key" = $'\x1b\x4f\x46' ]; then
key=$'\x1b\x5b\x34\x7e'
fi
$'\x1b\x5b\x32\x7e') # Insert
echo Insert Key
;;
In the above snippet, for example, when I press Home key and Insert key,
\x1b\x4f\x48
sequences for Home and \x1b\x5b\x32\x7e
sequences for Insert? Second snippet:
unset K1 K2 K3
read -s -N1 -p "Press a key: "
K1="$REPLY"
read -s -N2 -t 0.001
K2="$REPLY"
read -s -N1 -t 0.001
K3="$REPLY"
key="$K1$K2$K3"
In the above snippet, every time I pressed one key,
read -s -N2 -t 0.001
, why should specify the -t
(timeout) option and -N2
(nchars) to read 2 characters not 1?There are several questions asked...
The script is expecting escape sequences to be sent by special keys. On a typical keyboard, those are all of the keys which have a name or graphic symbol (such as ←, for left-cursor). By convention (there is no applicable standard) those keys send sequences of characters beginning with escape, with the second character often [
. For just those two characters, the hexadecimal codes are 0x1b
and 0x5b
, respectively (see ASCII table). The 0x4f
is the letter O
, and would be sent by a terminal's special keys in application mode.
The particular sequences sent by your Home and End keys use a slightly different convention from some of the other special keys, referred to a PC-style (see the xterm FAQ Why can't I use the home/end keys? for the background on that). Apparently the developer of the script decided to solve a problem related to that FAQ by ensuring that both variations of the sequences sent by Home and End would be translated into the VT220-style sequence.
The last question asks why it is necessary to do separate reads and use separate variables. That is because the sequence of characters sent by a special key may be transmitted over a network, and take more time than one of those read
operations allows. So only part of the sequence may be read at each try. The script collects the pieces and puts them together as one sequence of characters.