#bash #shell
#bash #оболочка
Вопрос:
Есть ли способ потребовать, чтобы клавиша enter нажималась с помощью read -n при достижении предела символов, вместо автоматического перехода к следующей строке в скрипте?
Например, в следующем сценарии:
echo "Please enter your credentials below"
read -p "Please enter your username: " -e -n 15 usern
read -p "Please enter your password: " -s -e -n 15 passw
После ввода 15 символов для имени пользователя он автоматически переходит к запросу пароля. Однако было бы удобнее для пользователя просто прекратить разрешать ввод после достижения 15 символов (помимо клавиши backspace и клавиши enter) и потребовать, чтобы пользователь нажимал enter, чтобы перейти к запросу пароля. В конце концов, именно так работает большинство логинов…
Я знаю, что я мог бы использовать оператор цикла while / if, ограничивающий ограничение символа в переменной usern (например, с помощью -gt ), но мне было интересно, как я мог бы конкретно ограничить пользователя нажатием либо backspace, либо enter (или даже клавиш со стрелками, если они хотят отредактировать один символ изих имя пользователя, но я не беспокоюсь об этом прямо сейчас), как только эти 15 символов будут достигнуты, и ТРЕБУЮТ, чтобы пользователь нажал enter, чтобы перейти к следующему приглашению.
Надеюсь, то, о чем я прошу, имеет смысл. Заранее спасибо всем!
Комментарии:
1. Сама
-n
опция уже растягивает то, для чегоread
предназначена. Оболочки не предназначены для написания отшлифованных пользовательских интерфейсов; они предназначены для объединения других языков.2. Если вы хотите ограничить username до 15 символов, я бы рекомендовал вам разрешить пользователю вводить все, что они хотят, а затем обрезать его после.
3. Возможно, с помощью таких программ, как
whiptail
. Я думаю, что со встроенными bash вы получили бы очень сложное решение, если бы оно вообще было.
Ответ №1:
Как упоминалось в комментариях, bash read
не может воспроизвести ожидаемое поведение для определенных ключей. Однако вы можете избежать использования read
, выполнив собственный синтаксический анализ ввода.
Некоторые моменты, которые следует учитывать:
- Необходимо настроить параметры строки терминала
stty
, чтобы избежать печати входных символов по мере их ввода (т. Е. Мы хотим печатать только наши сообщения, иначе символы будут дублироваться); - Эмулятор терминала должен поддерживать
VT100
escape-коды, чтобы стирать строку и перемещать курсор при перерисовке приглашения; - Символы можно сравнивать с помощью ascii-кода, но при нажатии enter мы не получаем прочитанный символ для самой новой строки. Однако, поскольку считываются другие пробельные символы, это не проблема.
Следующий сценарий реализует ожидаемое поведение, принимая символы до заданного предела (для пароля не печатаются введенные символы). Ввод отправляется только при нажатии enter.
#!/bin/sh
set -eu
parse() {
message=$1
var=$2
is_password=$3
input=
stty -icanon -echo
while true; do
# Clear line, move cursor to beginning, then print prompt
if [ "$is_password" -eq 1 ]; then
printf '33[2Kr'"$message "
else
printf '33[2Kr'"$message $input"
fi
# Read 1 character
i=$(dd bs=1 count=1 2>/dev/null)
# Was a backspace read?
if echo "$i" | grep -qP 'x7f'; then
# Remove last character
input=$(echo "$input" | sed 's/.$//')
# Only add read character if input field limit wasn't reached
elif [ ${#input} -lt 15 ]; then
input=$input$i
fi
# Was a newline read?
if [ -z "$i" ]; then
break
fi
done
stty icanon echo
eval "$var=$input"
}
echo "Please enter your credentials below"
parse "Please enter your username:" "usern" 0
printf "n%sn" "Read username: $usern"
parse "Please enter your password:" "userp" 1
printf "n%sn" "Read password: $userp"