Поддержка Ctrl + C / Ctrl + Z при "answer = $ (while! Head -c 1 | grep -i '[ny]'; do true; done)" - PullRequest
0 голосов
/ 24 мая 2019

Чтобы получить решение пользователя [Y/N], я использую функцию "yesno", которая содержит цикл:

answer=$( while ! head -c 1 | grep -i '[ny]' ; do true ; done )

Однако этот цикл блокирует консоль и его невозможно завершить нажатием Ctrl + C или Ctrl + Z .Добавление таких элементов, как [\x03] (ASCII для Ctrl + C ) или [\x1A] (ASCII для Ctrl + Z ) непомочь тоже.Как добавить эту функцию, сохраняя совместимость с POSIX и не полагаясь на другие инструменты?

#!/bin/sh

yesno () {
    printf "$1 [Y/N] "
    old_stty_cfg=$( stty -g )
    stty raw -echo
    answer=$( while ! head -c 1 | grep -i '[ny]' ; do true ; done )
    stty "$old_stty_cfg"
    if printf "$answer" | grep -iq "^y" ; then
        return 0
    else
        return 1
    fi
}

if yesno "Question?" ; then
    printf "yes\n"
    return 0
else
    printf "no\n"
    return 1
fi

1 Ответ

1 голос
/ 24 мая 2019

Комментарии об этом решении и его совместимости с POSIX - будут очень благодарны!

#!/bin/sh
enter=$( printf '\015' )
ctrl_c=$( printf '\003' )
ctrl_x=$( printf '\030' )
ctrl_z=$( printf '\032' )

yesno () {
    printf '%b [Y/N] ' "$1"
    old_stty_cfg=$( stty -g )
    stty raw -echo
    while true ; do
        answer=$( head -c 1 )
        case $answer in *"$ctrl_c"*|"$ctrl_x"*|"$ctrl_z"*)
            stty "$old_stty_cfg"
            exit 1
            ;;
            *"y"*|"Y"*)
            stty "$old_stty_cfg"
            return 0
            ;;
            *"n"*|"N"*)
            stty "$old_stty_cfg"
            return 1
            ;;
        esac
    done
}

if yesno "Question?" ; then
    printf "yes\n"
    exit 0
else
    printf "no\n"
    exit 1
fi
...