bashscript для виявлення натискання клавіші правої стрілки


9

Чому це завжди виявляється як істинне, навіть якщо код клавіші не є клавішею стрілки праворуч?

stty_state=`stty -g`
stty raw; stty -echo
keycode=`dd bs=1 count=1 2>/dev/null`
stty "$stty_state"  

echo $keycode

if [ "$keycode"=39 ]; then
echo "Right Arrow Key Pressed!"
fi

Відповіді:


16

Ви (ймовірно) прочитали перший із двох байтів. $keycodeу вашому сценарії буде ESC, коли натискається клавіша зі стрілкою.

Клавіші зі стрілками можуть бути:

\x1b + some value

Він завжди оцінюється як істинний через відсутність пропусків у умовному вираженні.

Редагувати: оновлення цього твердження.

Ваша ifфункція працює над статусом виходу [команди. [Команда еквівалентна test. Те, що це команда, є дуже важливим фактом. Як команда, вона вимагає пробілів між аргументами. Далі [команда особлива тим, що вона вимагає ]в якості останнього аргументу.

[ EXPRESSION ]

Команда виходить зі статусом, визначеним EXPRESSION. 1 або 0, правда чи хибність .

Це не екзотичний спосіб написання дужок. Іншими словами, це не є частиною ifсинтаксису, як, наприклад, у C:

if (x == 39)

Автор:

if [ "$keycode"=39 ]; then

ви видаєте:

[ "$keycode"=39 ]

який розширюється до

[ \x1b=39 ]

тут \x1b=39читається як один аргумент. Коли testабо [дається один аргумент, він закінчується помилковим, лише якщо EXPRESSION є нульовим - чого ніколи не буде. Навіть якщо він $keycodeбув порожнім, це призведе до =39(що не є нульовим / порожнім).

Ще один спосіб поглянути на це - сказати:

if 0 ; then # When _command_ exit with 0.
if 1 ; then # When _command_ exit with 1.

Прочитайте ці запитання та відповіді для більш детальної інформації - а також обговорення щодо [vs [[:

У цьому плані ви також можете дослідити тики `` vs $( )


Послідовність втечі багатобайтових клавіш зі стрілками:

Як згадувалося вгорі: ви (швидше за все) прочитали перший із двох байтів. $keycodeу вашому сценарії буде ESC, коли натискається клавіша зі стрілкою.

Стрілка та інші спеціальні клавіші призводять до того, що послідовності втечі повинні бути відправлені в систему. В 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 - це схоже на змішування між десятковою та шістнадцятковою. Перший байт у послідовності відхилення - це значення ASCII ESC , яке становить десятковий 27 і шістнадцятковий 0x1b, а десятковий 39 - шістнадцятковий 0x27. )


2
Перша проблема у питанні полягає в тому, що =в тесті немає пробілів, що оточують знак, тому він розбирається просто як не порожній рядок і, отже, є істинним. Те, що клавіші зі стрілками є декількома байтами, є окремим питанням.
wurtel

2
Гм, це речення не має великого контексту, як є, я читав це, як думав, що є частиною пояснення багатобайтових послідовностей, про які я вже знав.
wurtel

2
@wurtel: Так. До неясного я здогадуюсь. З'ясуйте, що колись одне пояснення [- це вбудована команда, люди зрозуміють, чому простори важливі набагато швидше. (Використовувати дужки замість дужок не просто дивним способом башти). Зараз доведеться закінчуватися. Оновлення ще раз назад.
користувач367890
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.