Вы (вероятно) читаете сначала из двух + байтов. $keycode
в вашем скрипте будет ESC при нажатии клавиши со стрелкой.
Клавиши со стрелками могут быть:
\x1b + some value
Он всегда оценивается как true из-за отсутствия пробелов в условном выражении.
Изменить: обновление этого заявления.
Ваш if
действует на выходе из [
команды. Команда [
эквивалентна test
. Тот факт, что это команда, является очень важным фактом. В качестве команды требуются пробелы между аргументами. Кроме того, [
команда особенная, поскольку она требует ]
последнего аргумента.
[ EXPRESSION ]
Команда выходит со статусом, определенным EXPRESSION. 1 или 0, правда или ложь .
Это не экзотический способ написать круглые скобки. Другими словами, он не является частью if
синтаксиса, как, например, в C:
if (x == 39)
По:
if [ "$keycode"=39 ]; then
вы выпускаете:
[ "$keycode"=39 ]
который расширяется до
[ \x1b=39 ]
здесь \x1b=39
читается как один аргумент. Когда test
или [
дается один аргумент, он завершается со значением false, только если EXPRESSION имеет значение null, чего никогда не будет. Даже если бы он $keycode
был пустым, это привело бы к =39
(который не является нулевым / пустым).
Другой способ взглянуть на это так: вы говорите:
if 0 ; then # When _command_ exit with 0.
if 1 ; then # When _command_ exit with 1.
Прочитайте эти вопросы и ответы для получения более подробной информации - а также обсуждение [
vs [[
:
В связи с этим вы также можете исследовать тики назад `` против $( )
Многобайтовая escape-последовательность с клавишами со стрелками:
Как упомянуто сверху: вы (вероятно) читаете сначала из двух + байтов. $keycode
в вашем скрипте будет ESC при нажатии клавиши со стрелкой.
Стрелка и другие специальные клавиши приводят к тому, что в систему отправляются escape-последовательности . В ESC байтовые сигналы , которые «здесь приходит несколько байтов , которые должны быть истолкованы по- разному» . Что касается клавиш со стрелками , которые будут ASCII - [
следуют ASCII A
, B
, C
или D
.
Другими словами, вы должны анализировать три байта при работе с клавишами со стрелками.
Вы можете попробовать что-то в этом направлении, чтобы проверить:
{ stty_state=$(stty -g)
stty raw isig -echo
keycode=$(dd bs=8 conv=sync count=1)
stty "$stty_state"
} </dev/tty 2>/dev/null
printf %s "$keycode" | xxd
Уступать:
HEX ASCII
1b 5b 41 .[A # Up arrow
1b 5b 42 .[B # Down arrow
1b 5b 43 .[C # Right arrow
1b 5b 44 .[D # Left arrow
| | |
| | +------ ASCII A, B, C and D
| +--------- ASCII [
+------------ ASCII ESC
Не уверен, насколько это переносимо, но раньше играл с таким кодом для ловли клавиш со стрелками. Нажмите, q
чтобы выйти:
while read -rsn1 ui; do
case "$ui" in
$'\x1b') # Handle ESC sequence.
# Flush read. We account for sequences for Fx keys as
# well. 6 should suffice far more then enough.
read -rsn1 -t 0.1 tmp
if [[ "$tmp" == "[" ]]; then
read -rsn1 -t 0.1 tmp
case "$tmp" in
"A") printf "Up\n";;
"B") printf "Down\n";;
"C") printf "Right\n";;
"D") printf "Left\n";;
esac
fi
# Flush "stdin" with 0.1 sec timeout.
read -rsn5 -t 0.1
;;
# Other one byte (char) cases. Here only quit.
q) break;;
esac
done
(Как второстепенное примечание вы также (намереваетесь) проверить десятичную 39 - которая выглядит как смешивание десятичной и шестнадцатеричной. Первый байт в escape-последовательности - это значение ASCII ESC , которое является десятичным 27 и шестнадцатеричным 0x1b
, а десятичное 39 - шестнадцатеричным 0x27
. )