Подсчет количества входов, предоставленных пользователем - PullRequest
0 голосов
/ 20 января 2020

Описание: у меня есть скрипт, который начинается с предупреждения / вопроса, заданного пользователю. Мне нужно, чтобы пользователь ответил да / у или нет / н.

Проблема: хотя у меня есть условие, чтобы убедиться, что пользователь дает один из следующих ответов, представленных выше, мне также нужно сделать так, чтобы пользователь предоставил только ОДИН ввод. Я пытался использовать

[ "$#" -eq 1 ] или [ $# -eq 1 ], но ни один из этих условий, похоже, не работает для решения проблемы

, вот что я до сих пор имею: ...

#!/bin/bash
#
# Descritpion: some Windows OS script
#
# 

printf "(!)WARNING(!): 1. The this program is ONLY compatible with Windows operating systems. "
printf "2. You will NEED to be logged in as an ADMIN in order to fully make use of the '*****' script.\n" 
printf "Would you like to continue? yes or no (y/n): "

#would it be cleaner to use "case" rather than a "while" w/ multiple conditionals? (01.19.2020)
read opt

while (true)
do
        if [ $opt == yes ] || [ $opt == y ]
        then
                printf "continue. \n"
                break

        elif [ $opt == no ] || [ $opt == n ]
        then
                printf "OK, exiting the script! \n"
                exit 0

        #elif [ "$#" -ne 1 ]
        #then
        #       "Too many arguments have been provided, please try again. \n"
        #       read opt
        else
                printf "The opition you provided is not recognized, please try again. \n"
                read opt
        fi
done

Ответы [ 3 ]

0 голосов
/ 20 января 2020

Взгляните на read опции

читать: читать [-ers] [-u fd] [-t тайм-аут] [-p приглашение] [-a массив] [-n nchars] [-d delim] [name ...]

Одна строка считывается из стандартного ввода или из файлового дескриптора FD, если указана опция -u, и первое слово присваивается первому NAME, второе слово ко второму NAME и т. Д., Причем оставшиеся слова присваиваются последнему NAME. Только символы, найденные в $ IFS, распознаются как разделители слов. Если NAME не указаны, прочитанная строка сохраняется в переменной REPLY. Если указана опция -r, это означает «необработанный» ввод, и экранирование backsla sh отключено. Опция -d заставляет чтение продолжаться до тех пор, пока не будет прочитан первый символ DELIM, а не перевод строки. Если указана опция -p, строка PROMPT выводится без завершающего перевода строки перед попыткой чтения. Если указан параметр -a, прочитанные слова присваиваются последовательным индексам ARRAY, начиная с нуля. Если указан ключ -e, а оболочка является интерактивной, для получения строки используется readline. Если -n предоставляется с ненулевым аргументом NCHARS, чтение возвращается после чтения символов NCHARS. Опция -s приводит к тому, что ввод, поступающий из терминала, не будет отображаться.

Вы сможете упростить ваш скрипт, используя некоторые из них.

0 голосов
/ 20 января 2020

Прочитайте ввод и проанализируйте его точно. Решите, хотите ли вы игнорировать пробелы или нет. Вы могли бы даже использовать регулярное выражение, чтобы сделать входные данные отформатированными так, как вы хотите.

  1. while (true) - это ненужное использование subshell. Просто while true.
  2. if [ $opt == yes ] не будет работать, если opt содержит пробелы, например, пользовательский ввод y e s. Он выйдет с ненулевым состоянием выхода и напечатает сообщение об ошибке в стандартном потоке ошибок. Как правило, всегда указывайте расширения переменных. Всегда "$opt", никогда $opt. Скорее всего, это ошибка, которую вы просите исправить.
  3. Также расширение == является bash. Используйте = для сравнения строк.
  4. Косметика: [ $opt == yes ] || [ $opt == y ] ненужный запускает два процесса в случае сбоя первого. Просто запустите один процесс [ "$opt" = yes -o "$opt" = y ]. Но первый может быть более понятным.
  5. read opt игнорирует начальные и конечные пробелы и удаляет косые черты \. Используйте IFS= read -r opt, чтобы прочитать всю строку в точности так, как она есть.
  6. Используйте shellcheck. net для проверки ваших сценариев.
  7. $# - это количество аргументов, переданных сценарию , Это не связано с тем, что делает read. read сохраняет ввод в переменную.

Итак:

while true; do
   if ! IFS= read -r opt; then
      echo "ERROR: END OF INPUT!" >&2
      exit 2
   fi
   case "$opt" in
   y|yes) printf 'continue. \n'; break; ;;
   n|no) printf 'OK, exiting the script! \n'; exit 1; ;;
   *) printf 'The opition you provided is not recognized, please try again. \n'; ;;
   esac
done
0 голосов
/ 20 января 2020

Не идеальное решение, но оно включает объяснение того, почему $ # не работает так, как вы ожидаете:

$ # возвращает количество аргументов, переданных функции. Вы прочитали 'opt' как пользовательский ввод, а не аргументы функции.

Одно из решений может заключаться в том, чтобы обернуть вашу бесконечность, в то время как l oop, внутри функции, а затем передать в нее $ opt. Тогда это будет аргумент (ы) вашей функции, и вы можете использовать $ #, чтобы посчитать, сколько их. Для получения подробной информации о работе многих встроенных функций в bash, вы можете попробовать:

man bash

, но я принимаю, что там есть lot информации. Вы можете искать соответствующие слова, обычно используя "/ {searchstring}" (но вам, вероятно, потребуется "экранировать" специальные символы, в этом случае: "/ \ $ \ #")

...