Как прочитать только один символ в сценарии оболочки

Мне нужна аналогичная опция, такая как getche() в C. Как я могу прочитать только один символ, введенный из командной строки?

С помощью команды read мы можем это сделать?


person footy    schedule 04.01.2012    source источник


Ответы (5)


В ksh вы можете сделать:

stty raw
REPLY=$(dd bs=1 count=1 2> /dev/null)
stty -raw
person Diego Torres Milano    schedule 04.01.2012

В bash это может сделать read:

read -n1 ans
person SiegeX    schedule 04.01.2012
comment
read -p Введите любой символ: -n1 ans; echo -e \nВы ввели: $ans - person dimir; 04.01.2012

read -n1 работает для bash

Режим stty raw предотвращает работу ctrl-c и может привести к тому, что вы застрянете в цикле ввода без выхода. Также на странице руководства говорится, что stty -raw не гарантирует возврат вашего терминала в то же состояние.

Таким образом, использование ответа dtmilano с использованием stty -icanon -echo позволяет избежать этих проблем.

#/bin/ksh
## /bin/{ksh,sh,zsh,...}

# read_char var
read_char() {
  stty -icanon -echo
  eval "$1=\$(dd bs=1 count=1 2>/dev/null)"
  stty icanon echo
}

read_char char
echo "got $char"
person fess .    schedule 04.05.2015
comment
Это также работает для ash (проверено с BusyBox v1.10.2) и для #!/bin/sh, являющегося dash в debian. - person Sam; 26.12.2018
comment
Привет, признаюсь. Я считаю своим долгом сообщить вам об этом вопросе и этот мета-вопрос. И я полностью намерен сдержать свое слово (может быть, не сразу после того, как я набрал 75, это опустило бы меня до 25, и тогда я мог бы потерять комментарии везде, но как только я достигну 100, я буду использовать систему вознаграждений) - person Sam; 26.12.2018
comment
@Sam Сэм, я бы посоветовал вам пока сохранить свою репутацию, так как вам понадобится репутация для разных вещей: . Я предлагаю награду, так что не волнуйтесь. - person Cœur; 26.12.2018

read -n1

читает ровно один символ из ввода

echo "$REPLY"

выводит результат на экран

документ: https://www.computerhope.com/unix/bash/read.htm

person Sergey Gurin    schedule 06.02.2019

Некоторые люди имеют в виду под «вводом из командной строки» аргумент, переданный команде вместо чтения из стандартного ввода... так что, пожалуйста, не стреляйте в меня. Но у меня есть (возможно, не самое сложное) решение для STDIN!

При использовании bash и наличии данных в переменной вы можете использовать расширение параметра

${parameter:offset:length}

и, конечно, вы можете выполнить это с заданными аргументами ($1, $2, $3 и т. д.)

Скрипт

#!/usr/bin/env bash

testdata1="1234"
testdata2="abcd"

echo ${testdata1:0:1}
echo ${testdata2:0:1}
echo ${1:0:1} # argument #1 from command line

Исполнение

$ ./test.sh foo
1
a
f

чтение из стандартного ввода

Скрипт

#!/usr/bin/env bash

echo please type in your message:
read message
echo 1st char: ${message:0:1}

Исполнение

$ ./test.sh 
please type in your message:
Foo
1st char: F
person Mirko Steiner    schedule 06.02.2019
comment
Чтение отдельных символов больше связано с условным чтением, ожиданием или выполнением работы по мере поступления символов, чем с изоляцией одного символа, предполагая, что вы уже успешно читаете вперед. Это блокируется на неопределенный срок, с символом 1 или без него, попеременно потребляя все, что может, и ожидая большего, пока не потребляет какой-то разделитель. Он отбрасывает разделитель, который может быть символом новой строки, EOF или первым символом, который вы пытаетесь прочитать (в этом случае длина равна 0). Допустимо в некоторых случаях, но... предостережение. - person John P; 11.12.2020