Что я должен рассмотреть для записи сценария, который воздействует на нажатие клавиши?

Я всегда использовал Unetbootin, чтобы сделать эти типы установок. Это - автономный исполняемый файл, таким образом, нет ничего для установки, просто загрузите его и работайте.

          ss of unetbootin

            ss of unetbootin

3
12.02.2015, 15:41
2 ответа

Что касается чтения оболочки, то это - независимо от того, ограничиваете ли вы его общее количество байтов на чтение или нет - это все равно не даст вам нажатий клавиши на чтения . Будет только фиксированное количество символов на чтение . Чтобы получить нажатие клавиши на чтение , вам необходимо заблокировать ввод - и лучший способ сделать это, вероятно, - dd .Это функция оболочки, которую я написал пару месяцев назад, когда экспериментировал с блокировкой dd на терминальном вводе / выводе:

printkeys()(    IFS= n=1
    set -f -- "$(tty <&2)"
    exec    <${1##[!/]*};set \\t
    _dd()(  c=conv=sync,unblock i=ibs=72 b=bs=8
            dd bs=7 ${c%,*} |   dd $i o$b c$b $c
    )       2>/dev/null
    trap "  trap '' TTOU TTIN
            stty '$(stty -g
            stty raw isig inlcr)'   "   INT EXIT
    _dd |while  ${2:+:} read -r c   ||  exit 2
            do  case $#:$c in (1:): ;; 
        (*:?*)  set ":%d$@"         \
                    \'${c%"${c#?}"} ;
                c=${c#?}            ;; 
        (*)     printf "$@"         ;
        [ 0 -eq $((n=n<4?n+1:0)) ]  &&
                set '\n\r'||set \\t ;;  esac
        done
)

Видите ли, в приведенном выше случае ввод терминала фильтруется по двум dd обрабатывает конвейер. Терминал устанавливается с stty в режим raw в ловушке , которая также восстанавливает конечное состояние при прерывании INT или EXIT на то, что было, когда функция была вызвана (что, вероятно, можно сделать с помощью CTRL + C или любой другой клавиши прерывания) . В режиме raw терминал сбрасывает ввод любому считывающему устройству, как только он поступает - нажатие клавиши за нажатием клавиши. Он не просто отправляет байт за раз; он выталкивает весь буфер, как только это возможно. И поэтому, когда вы, например, нажимаете стрелку ВВЕРХ, и ваша клавиатура отправляет escape-последовательность, например:

^[[A

... это три байта, и она нажимает все сразу.

dd спроектирован так, чтобы удовлетворить любое чтение, как только оно будет предложено - независимо от того, насколько высоко вы установите его ibs = . Это означает, что, хотя я установил его с помощью ibs = 7 , когда терминал отправляет только три байта, чтение все равно завершается. С этим трудно справиться с большинством других утилит, но dd conv = sync заполняет разницу w / \ 0NUL байтов. Поэтому, когда вы нажимаете стрелку ВВЕРХ на клавиатуре, dd считывает три байта и записывает 7 в следующий dd - три байта в escape-последовательности и еще 4 \ 0NUL с.

Но для того, чтобы получить эти данные при чтении оболочки, вы должны снова заблокировать их, поэтому следующий dd синхронизирует свой входной буфер до 72 байтов - но он также conv = разблокировать s это. С преобразованием разблокировать , dd разбивает свой ввод на \ n разделителей ewline для своего счетчика cbs = , который здесь равен 8. С синхронизация и разблокировка (или блок ) преобразования, dd не синхронизируется на \ 0NUL s, а скорее на конечных пробелах. Таким образом, для каждых 7 байтов первый dd записывает в канал между ними, второй dd буферизует 72 байта - первые несколько соответствуют нажатию клавиш, затем \ 0NUL с, затем 65 пробелов в конце каждого чтения.

Другая вещь, которую выполняет unblock , - это убирает конечные пробелы - он съедает столько пробелов, сколько может появиться в конце каждого из его блоков преобразования cbs = . Таким образом, поскольку dd записывает вывод с obs = 8 байт на запись, он записывает 9 строк за одно чтение в 2 общих операциях записи в выходной канал. Первая запись - это первая строка, состоящая из 7 байтов, считанных из входного канала, и завершающего символа новой строки - еще одного байта. Следующая запись - 8 новых строк - все сразу и подряд - еще 8 байтов - потому что dd съедает все 8 пробелов для каждого из этих 8 блоков преобразования.

С другой стороны этих двух dd s оболочка , в то время как цикл считывает s построчно.Он может игнорировать пустые строки - потому что терминал все равно преобразует все символы новой строки в возврат каретки при выводе в соответствии с параметром inlcr stty . Но когда он обнаруживает даже один байт в $ c после того, как ввод оболочки считывает в его значение, тогда у вас есть нажатие клавиши - и целикомпока ваша клавиатура не отправляет более 7 байтов на нажатие клавиши (хотя для этого просто потребуется другой коэффициент блокировки) .

Когда оболочка нажимает клавишу в $ c , она выполняет итерацию по байту за байтом и разбивает его на массив, разделенный на ' символов, затем printf s десятичные значения для каждого байта в $ c сразу. Если вы запустите эту функцию, вы должны получить следующий результат:

a:97    b:98    c:99    d:100   e:101
f:102   ;:59    ^M:13   ^M:13   ^M:13
s:115   a:97    d:100   f:102    :32
':39    ':39    ':39    a:97    s:115
d:100   f:102   ;:59    ':39    ^[[A:27:91:65
^[[D:27:91:68   ^[[B:27:91:66   ^[[C:27:91:67   ^[[D:27:91:68   ^[[C:27:91:67
^[[A:27:91:65   ^[[D:27:91:68   ^[[C:27:91:67   ^[[B:27:91:66   ^[[D:27:91:68
^[[C:27:91:67   ^[[A:27:91:65   ^[[D:27:91:68   ^[[C:27:91:67   ^[[B:27:91:66

Потому что \ 0NUL , которые dd вставляет, чтобы заблокировать нажатия клавиш, испаряются, как только оболочка заполняет значение переменной с ее вводом - вы не можете поместить \ 0NUL s в переменную оболочки (в любой оболочке, кроме zsh - в этом случае ее можно настроить таким образом) . Насколько мне известно, это должно работать в любой оболочке - и это определенно работает в bash , dash и ksh93 . Он может даже надежно обрабатывать многобайтовый ввод, но я не буду на это ругаться.

В демонстрационном выводе выше фактическому выводу функции для каждой записи предшествует другая информация, которую она не записывает. Каждый отображаемый символ, предшествующий каждому первому появлению : в любой из вышеперечисленных последовательностей, на самом деле является эхо терминала, которое можно настроить с помощью stty echo или - эхо . Остальное - это то, что печатается как вывод функции - и оно печатается, как вы можете видеть, сразу после ввода.

2
27.01.2020, 21:19

С bash вы можете использовать параметр -n для встроенного чтения , чтобы ограничить количество читаемых символов без необходимости новой строки:

#!/bin/bash

echo "Ready? [Y/n]: "
read -n 1 y_or_n
echo

case "$y_or_n" in
    [Yy]|"")
        echo "you said yes"
        ;;
    *)
        echo "you said no"
        ;;
esac

Это работает независимо от того, вызывается ли bash как sh или bash .

См. справку по чтению или справочную страницу bash для получения дополнительных сведений.

Обратите внимание, что другие оболочки могут не поддерживать параметр -n для чтения . тире , например, нет.

2
27.01.2020, 21:19

Теги

Похожие вопросы