Неожиданный EOF и синтаксическая ошибка

9

В настоящее время я пишу свой третий скрипт оболочки, и у меня возникла проблема. Это мой сценарий:

#!/bin/bash
echo "choose one of the following options : \
  1) display all current users \
  2) list all files \
  3) show calendar \
  4) exit script"

while read  
do  
 case in  
        1) who;;  
        2) ls -a;;  
        3) cal;;  
        4) exit;;  
 esac    
done

когда я пытаюсь запустить скрипт, он говорит это:

line2 : unexpected EOF while looking for matching '"'  
line14 : syntax error: unexpected end of file.    

Что я делаю неправильно?

Swifty124
источник
1
Конечно, вы имеете в виду «EOF», а не «ECF»?
10

Ответы:

5

Проблема в том, что в вашем caseутверждении отсутствует тема - переменная, которую он должен оценивать. Следовательно, вы, вероятно, хотите что-то вроде этого:

#!/bin/bash
cat <<EOD
choose one of the following options:
1) display all current users
2) list all files
3) show calendar
4) exit script
EOD

while true; do
    printf "your choice: "
    read
    case $REPLY in
        1) who;;
        2) ls -a;;
        3) cal;;
        4) exit;;
    esac    
done

Здесь caseиспользуется переменная по умолчанию, $REPLYкоторая readзаполняется, когда ей не дано никаких имен переменных (см. help readПодробности).

Также обратите внимание на изменения: printfиспользуется для отображения подсказки в каждом раунде (и не добавляет новую строку), catиспользуется для печати инструкций в несколько строк, чтобы они не переносились и их было легче читать.

peterph
источник
6

Давайте не будем забывать select:

choices=( 
    "display all current users" 
    "list all files" 
    "show calendar" 
    "exit script"
)
PS3="your choice: "
select choice in "${choices[@]}"; do
    case $choice in
        "${choices[0]}") who;;
        "${choices[1]}") ls -a;;
        "${choices[2]}") cal;;
        "${choices[3]}") break;;
    esac
done
Гленн Джекман
источник
1
Это выглядит как самый чистый ответ на данный момент. Он использует select, который был разработан, чтобы делать именно то, что требует OP. Он помещает выбор в массив, который является отличным способом для обработки таких данных, и делает его доступным для использования в другом месте скрипта. Он использует break, а не exit, поэтому скрипт может делать что-то еще после выполнения этой части.
Джо
2

Давайте сначала попробуем для одного случая. Я буду использовать read -pдля чтения пользовательского ввода в переменную с optпоследующим оператором case, как показано ниже.

#!/bin/bash
read -p "choose one of the following options : \
  1) display all current users \
  2) list all files \
  3) show calendar \
  4) exit script" opt
case $opt in
1) who;;
2) ls -a;;
3) cal;;
4) exit;;
esac

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

Итак, мы можем сделать это с помощью whileцикла, как показано ниже. Я установил переменную optс начальным значением равным 0. Теперь я выполняю итерации в whileцикле, пока optпеременная имеет значение 0 (поэтому я сбрасываю optпеременную как 0 в конце caseоператора).

#!/bin/bash
opt=0;
while [ "$opt" == 0 ]
do
read -p "choose one of the following options : \
  1) display all current users \
  2) list all files \
  3) show calendar \
  4) exit script" opt

case $opt in
1) who;;
2) ls -a;;
3) cal;;
4) exit;;
esac
opt=0
done
Рамеш
источник
0

Я бы лично поставил «время» в начале кода. Если затем вы последуете за ним с помощью символа :, он позволит вам зацикливаться столько раз, сколько вы пожелаете. Вот как бы я это написал.

while :
do
    echo "choose one of the following options : \
      1) display all current users \
      2) list all files \
      3) show calendar \
      4) exit script"
    read string
    case $string in
        1)
            who
            ;;

затем продолжайте вопросы и заканчивайте

esac
done
Джо Дейл
источник