bash — если код возврата> = 1 повторно запустить скрипт, начать с начала

#bash #shell #goto

#bash #оболочка #переход

Вопрос:

У меня есть скрипт bash, который печатает заголовок и проверяет значение «Y» или «N».

Когда кто-то вводит текст, который не равен «Y» или «N», я хотел бы отправить их обратно в начало скрипта, чтобы он снова напечатал заголовок и вопрос.

Я знаю, что вы можете сделать это с помощью goto, но мне было интересно, есть ли другой способ, потому что я слышал, что многие люди говорят, что вам не следует использовать goto или что он устарел. Верно это или нет, я хотел бы посмотреть, есть ли у кого-нибудь еще способ решить эту проблему.

Заранее спасибо.

Ответ №1:

Вы могли бы реализовать это в цикле:

 while [ !$exit_loop ]
do
    echo "enter choice - "
    read -n 1 input
    case "$input" in
     y|Y) $exit_loop = 1;;
     n|N) $exit_loop = 1;;
     *) echo "invalid choice";;
    esac
done
 

Лично я не нахожу разницы между использованием перехода / цикла или любых других средств. Я бы всегда говорил использовать то, что наиболее подходит для данной ситуации — для вашей я бы использовал goto .

например, если у вас есть несколько отступов, охватывающих много строк, и вам нужно вернуться к началу функции, я бы использовал goto — это намного проще понять в его контексте.

Комментарии:

1. Вы можете упростить с while true; do case помощью оператора and, который заменит на простой if , и, если совпадет, будет break . Так что вам не нужна переменная plus ( $exit_loop ) .

2. Очень верно. Увы, не зная, что op хотел сделать в цикле, я просто собрал это вместе 🙂

Ответ №2:

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

 read -p "Yes? Or no? " yn
case $yn in
  [YyNn]) ;;
  *) exec "$0" "$@"
esac
 

Ответ №3:

Если вам нужен более структурированный подход, вы можете использовать цикл while или until .

Ответ №4:

Ниже приведен пример (слегка упрощенный) с использованием предложения @Michael. Условие выхода находится в цикле while, но пользователь также может выполнить промежуточное действие, чтобы решить, какое действие предпринять:

 while [[ ! "${action-}" =~ ^[SsRr]$ ]]
do
    echo "What do you want to do?"
    read -n 1 -p $'[d]iff, [s]kip, [S]kip all, [r]eplace, [R]eplace all: n' action

    if [[ "${action-}" =~ ^[Dd]$ ]]
    then
        diff "$target_path" "$source_path"
    fi
done
 

Комментарии:

1. Я не видел ничего подобного раньше, [[ ! «$ {action-}» = ~ ^[SsRr] $ ]], аккуратно.

Ответ №5:

 echo "Hello User, are you ready to learn some Linux?"
while true; do
    echo "Please enter y/n:"
    read a
    bfunc() {
        if [ "$a" == "y" ]
        then
            echo "That is great, lets get started!"
            echo "This Script is under construction, functionality coming soon"
            exit 0
        elif [ "$a" == "n" ]
        then
            echo "That is too bad, see you next time!"
            echo "You are now exiting the script"
            exit 0
        else [ "$a" != "y||n" ]
            echo "Please only enter y or n!" 
        fi
    }
    bfunc
done
 

Комментарии:

1. Извините, я не знал, что для создания кода нужны 4 пробела, но это работает!

2. Нет, на самом деле это не так; в частности, else [ "$a" != "y||n" ] это не синтаксическая ошибка, но и совсем не то, что вы думаете. Определение функции внутри цикла также довольно … оригинально.

3. Это мой первый bash-скрипт, и он работает так, как я предполагал. Можете ли вы объяснить, почему это неправильно?