bash scripting-чтение одного нажатия клавиши, включая специальные клавиши enter и space

не уверен, должен ли я поместить это в stackoverflow или unix.stackexchange, но я нашел некоторые как вопросы вот, так вот он идет.

Я пытаюсь создать скрипт, который будет вызываться .bashrc, который позволяет мне выбрать один из двух вариантов на основе одного нажатия клавиши. Это было бы не сложно, но я хочу, чтобы два ключа, соответствующие двум вариантам, были пробелом и вводом.

вот что я получил так далеко:

#!/bin/bash

SELECT=""
while [[ "$SELECT" != $'x0a' && "$SELECT" != $'x20' ]]; do
    echo "Select session type:"
    echo "Press <Enter> to do foo"
    echo "Press <Space> to do bar"
    read -s -N 1 SELECT
    echo "Debug/$SELECT/${#SELECT}"
    [[ "$SELECT" == $'x0a' ]] && echo "enter" # do foo
    [[ "$SELECT" == $'x20' ]] && echo "space" # do bar
done

следующий вывод-это то, что я получаю, если я нажимаю enter, space, backspace и x:

:~$ bin/sessionSelect.sh
Select session type:
Press <Enter> to start/resume a screen session
Press <Space> for a regular ssh session
Debug//0
Select session type:
Press <Enter> to start/resume a screen session
Press <Space> for a regular ssh session
Debug//0
Select session type:
Press <Enter> to start/resume a screen session
Press <Space> for a regular ssh session
Debug//1
Select session type:
Press <Enter> to start/resume a screen session
Press <Space> for a regular ssh session
Debug/x/1

таким образом, как ввод, так и Пробел приводят к пустому выбору. Невозможно отличить одно от другого. Я попытался добавить-d ' D ' к параметрам чтения, но это не помогло. Может, кто-нибудь укажет мне верное направление.

версия bash будет 4.2 btw.

3 ответов


попробуйте установить разделитель чтения в пустую строку, затем проверьте встроенную переменную $REPLY:

read -d'' -s -n1

по какой-то причине я не мог заставить его работать, указывая переменную.


#!/bin/bash
SELECT=""
# prevent parsing of the input line
IFS=''
while [[ "$SELECT" != $'\x0a' && "$SELECT" != $'\x20' ]]; do
  echo "Select session type:"
  echo "Press <Enter> to do foo"
  echo "Press <Space> to do bar"
  read -s -N 1 SELECT
  echo "Debug/$SELECT/${#SELECT}"
  [[ "$SELECT" == $'\x0a' ]] && echo "enter" # do foo
  [[ "$SELECT" == $'\x20' ]] && echo "space" # do bar
done

есть несколько вещей, о read, которые актуальны здесь:

  • он читает одну строку
  • строка разбивается на поля, как при разбиении слов

поскольку вы читаете один символ, это означает, что вступление Enter приведет к пустой переменной.

более того, по умолчанию правила разбиения слов, ввод пробел также приведет к пустой переменной. Хорошая новость это то, что вы могли бы справиться с этой частью, установив IFS.

изменить read заявление:

IFS= read -s -n 1 SELECT

и ожидайте нулевую строку вместо $'\x0a' при входе в Enter.