Команда read в Bash
Bash поставляется с рядом встроенных команд, которые можно использовать в командной строке или в сценариях оболочки.
В этой статье мы рассмотрим встроенную команду read .
Встроенное read Bash
read — это встроенная команда bash, которая считывает строку из стандартного ввода (или из файлового дескриптора) и разбивает строку на слова. Первое слово присваивается первому имени, второе — второму имени и так далее.
Общий синтаксис встроенной функции read имеет следующий вид:
Чтобы проиллюстрировать, как работает команда, откройте терминал, введите read var1 var2 и нажмите «Enter». Команда будет ждать, пока пользователь введет данные. Введите два слова и нажмите «Enter».
read var1 var2
Hello, World!
Слова присваиваются именам, которые передаются команде read качестве аргументов. Используйте echo или printf чтобы проверить это:
Вместо того, чтобы вводить текст на терминале, вы можете передать стандартный ввод для read с помощью других методов, таких как piping, here-string или heredoc :
echo "Hello, World!" | (read var1 var2; echo -e "$var1 n$var2")
Вот пример использования строки здесь и printf :
read -r var1 var2 printf "var1: %s nvar2: %sn" "$var1" "$var2"
Если команде read не задан аргумент, вся строка присваивается переменной REPLY :
echo "Hello, world!" | (read; echo "$REPLY")
Если количество аргументов, предоставленных для read , больше, чем количество слов, прочитанных из ввода, оставшиеся слова присваиваются фамилии:
echo "Linux is awesome." | (read var1 var2; echo -e "Var1: $var1 nVar2: $var2")
Var1: Linux Var2: is awesome.
В противном случае, если количество аргументов меньше количества имен, оставшимся именам присваивается пустое значение:
echo "Hello, World!" | (read var1 var2 var3; echo -e "Var1: $var1 nVar2: $var2 nVar3: $var3")
Var1: Hello, Var2: World! Var3:
По умолчанию read интерпретирует обратную косую черту как escape-символ, что иногда может вызывать неожиданное поведение. Чтобы отключить экранирование обратной косой черты, вызовите команду с параметром -r .
Ниже приведен пример, показывающий, как работает read при вызове с параметром -r и без него:
Как правило, вы всегда должны использовать read с параметром -r .
Изменение разделителя
По умолчанию при read строка разбивается на слова с использованием одного или нескольких пробелов, табуляции и новой строки в качестве разделителей. Чтобы использовать другой символ в качестве разделителя, присвойте его переменной IFS (внутренний разделитель полей).
echo "Linux:is:awesome." | (IFS=":" read -r var1 var2 var3; echo -e "$var1 n$var2 n$var3")
Когда IFS установлен на символ, отличный от пробела или табуляции, слова разделяются ровно одним символом:
echo "Linux::is:awesome." |
(IFS=":" read -r var1 var2 var3 var4; echo -e "Var1: $var1 nVar2: $var2 nVar3: $var3 nVar4: $var4")
Строка разделена четырьмя словами. Второе слово — это пустое значение, представляющее отрезок между разделителями. Он создан, потому что мы использовали два символа-разделителя рядом друг с другом ( :: .
Var1: Linux Var2: Var3: is Var4: awesome.
Для разделения строки можно использовать несколько разделителей. При указании нескольких разделителей присваивайте символы переменной IFS без пробела между ними.
Вот пример использования _ и - качестве разделителей:
echo 'Linux_is-awesome.' | (IFS="-_" read -r var1 var2 var3; echo -e "$var1 n$var2 n$var3")
Строка подсказки
При написании интерактивных сценариев bash вы можете использовать команду read для получения пользовательского ввода.
Чтобы указать строку приглашения, используйте параметр -p . Подсказка печатается перед выполнением read и не включает новую строку.
Как правило, вы будете использовать для read команды внутри в while цикл , чтобы заставить пользователя дать один из ожидаемых ответов.
Приведенный ниже код предложит пользователю перезагрузить систему :
while true; do read -r -p "Do you wish to reboot the system? (Y/N): " answer case $answer in [Yy]* ) reboot; break;; [Nn]* ) exit;; * ) echo "Please answer Y or N.";; esac done
Если сценарий оболочки просит пользователей ввести конфиденциальную информацию, например пароль, используйте параметр -s который сообщает read не печатать ввод на терминале:
read -r -s -p "Enter your password: "
Назначьте слова в массив
Чтобы присвоить слова массиву вместо имен переменных, вызовите команду read с параметром -a :
read -r -a MY_ARR "Linux is awesome." for i in "$MY_ARR[@]>"; do echo "$i" done
Когда даны и массив, и имя переменной, все слова присваиваются массиву.
Выводы
Команда read используется для разделения строки ввода на слова.
Если у вас есть какие-либо вопросы или отзывы, не стесняйтесь оставлять комментарии.
Linux read file mode
Вызов read() пытается прочитать count байт из файлового дескриптора fd в буфер, начинающийся по адресу buf. Для файлов, поддерживающих смещения, операция чтения начинается с текущего файлового смещения, и файловое смещение увеличивается на количество прочитанных байт. Если текущее файловое смещение находится за концом файла, то ничего не читается и read() возвращает ноль. Если значение count равно 0, то read() может обнаружить ошибки, описанные далее. При отсутствии ошибок, или если read() не выполняет проверки, то read() с count равным 0 возвращает 0 и ничего не меняет. Если значение count больше SSIZE_MAX, то результат не определён.
ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ
При успешном выполнении возвращается количество прочитанных байт (ноль означает конец файла), а позиция в файле увеличивается на это значение. Если количество прочитанных байт меньше, чем количество запрошенных, то это не считается ошибкой: например, это могло произойти из-за того, что прямо сейчас доступно меньшее количество байт (может быть из-за того, что позиция ближе к концу файла, или потому что выполняется чтение из канала или терминала), или потому что работа read() была прервана сигналом. См. также ЗАМЕЧАНИЯ. В случае ошибки возвращается -1, а errno устанавливается в соответствующее значение. В этом случае изменение позиции файла остаётся неопределённым (если это вообще происходило).
ОШИБКИ
EAGAIN Файловый дескриптор fd указывает на файл, не являющийся сокетом и помеченный как неблокирующий ввод/вывод (O_NONBLOCK), а чтение вызовет блокировку. См. open(2) для дальнейшей информации по флагу O_NONBLOCK. EAGAIN или EWOULDBLOCK Файловый дескриптор fd указывает на сокет и он помечен как неблокирующий (O_NONBLOCK), а чтение вызвало бы блокировку. POSIX.1-2001 позволяет вернуть любую ошибку в этом случае и не требует, чтобы эти константы имели одинаковое значение, поэтому переносимое приложение должно проверять обе эти возможности. EBADF fd не является допустимым файловым дескриптором или не открыт на чтение. EFAULT buf находится за пределами доступного вам адресного пространства. EINTR Вызов был прерван сигналом до того как были прочитаны данные; см. signal(7). EINVAL fd связан с объектом, не приспособленным для чтения; или файл был открыт с использованием флага O_DIRECT, и адрес, указанный в buf, значение, указанное в count или текущее смещение в файле, имеет недопустимое выравнивание. EINVAL fd был создан вызовом timerfd_create(2), а в read() был передан неверный размер буфера; подробней см. в timerfd_create(2). EIO Ошибка ввода/вывода. Например, это происходит когда процесс, находящийся в фоновой группе процессов, пытается выполнить чтение из своего управляющего терминала, и игнорирует или блокирует сигнал SIGTTIN или же его группа процессов осталась без родителя. Это также может случиться, если произошла низкоуровневая ошибка ввода-вывода при чтения с диска или ленты. EISDIR fd указывает на каталог. Могут также возникнуть другие ошибки, в зависимости от объекта, связанного с fd. POSIX позволяет системному вызову read(), который был прерван после чтения первого куска запрошенных данных, возвращать -1 (с errno, установленной в EINTR) или количество уже прочитанных байт.
СООТВЕТСТВИЕ СТАНДАРТАМ
ЗАМЕЧАНИЯ
В Linux read() (и похожие системные вызовы) передаст не больше 0x7ffff000 (2 147 479 552) байт, возвращая число байт, переданных на самом деле (это утверждение справедливо как к 32-битным, так и к 64-битным системам). На файловых системах NFS чтение небольших порций данных обновляет отметки времени только в первый раз, последующие вызовы не делают этого. Это вызвано кэшированием атрибутов с клиентской стороны, потому что большинство (если не все) клиентов NFS предоставляют серверу обновлять st_atime (время последнего доступа), а запросы на чтение, которые удовлетворяются из клиентского кэша, не вызывают обновления st_atime, потому что данные не читаются с сервера. Семантика UNIX может быть достигнута запретом кэширования атрибутов на стороне клиента, но в большинстве случаев это увеличит нагрузку на сервер и снизит производительность.
ДЕФЕКТЫ
Согласно POSIX.1-2008/SUSv4 раздел XSI 2.9.7 («Thread Interactions with Regular File Operations»): Следующие функции должны выполняться атомарно по отношению друг к другу, чтобы работать с обычными файлами или символическими ссылками так, как указано в POSIX.1-2008: … Среди перечисленных в программном интерфейсе есть read() и readv(2). И среди действий, которые должны выполняться атомарно между нитями (и процессами), если обновление файлового смещения. Однако в Linux до версии 3.14 это было не так: если два процесса с общим открытым файловым описанием (смотрите open(2)) выполняют read() (или readv(2)) одновременно, то операции ввода-вывода не атомарны при обновлении файлового смещения; в результате прочитанные двумя процессами блоки данных могут (некорректно) перекрываться. Эта ошибка исправлена в Linux 3.14.