Выбрать в цикле не запрашивать ввод - PullRequest
0 голосов
/ 06 сентября 2018

Я пытаюсь задать вопрос в цикле (например, запросить подтверждение для обработки каждого файла в каталоге).

Этот кусок кода отлично работает:

PS3="Dummy question ? "
select CHOICE_MADE in "Ans1" 'Ans2' 'Ans3'; do
    if [[ -n ${CHOICE_MADE} ]]; then
        printf "Choice made : %s\n" "${CHOICE_MADE}"
        break;
    fi
done

Мне нужно зациклить этот вопрос (заметьте, я называю переменную в цикле, чтобы избежать использования переменной $ REPLY по умолчанию):

while read -r TOTO; do
    PS3="Dummy question ? "
    select CHOICE_MADE in Ans1 Ans2 Ans3; do
        if [[ -n ${CHOICE_MADE} ]]; then
            printf "Choice made : %s\n" "${CHOICE_MADE}"
            break;
        fi
    done
done < <(echo Step1 Step2)

Выбор ничего не подсказывает.

Я не хочу использовать whiptail (который маскирует предыдущий вывод скрипта), диалоговое окно (должно быть установлено на debian) или любой графический интерфейс.

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

Заранее спасибо за помощь.

1 Ответ

0 голосов
/ 06 сентября 2018

Вы должны отметить две вещи, чтобы заставить это работать.

1) Неправильное использование `stdin`

Прежде всего, передав < (echo Step1 Step2) в свой цикл while, вы используете stdin, и поэтому подсказка вообще не ждет ввода (у него уже есть!).

Вы можете избавиться от него, используя файловые дескрипторы :

exec 3< <(echo Step1 Step2) ### Create fd "3" and put output of echo in it
while read -r TOTO <&3; do
    PS3="Dummy question ? "
    select CHOICE_MADE in Ans1 Ans2 Ans3; do
        if [[ -n ${CHOICE_MADE} ]]; then
            printf "Choice made : %s\n" "${CHOICE_MADE}"
            break
        fi
    done
done
exec 3>&- ### clean fd 3

Я оставил без изменений остаток кода.

2) Неправильное использование `read`

Еще одна вещь, о которой вы должны подумать, это то, что read -r будет построчно читать то, что вы ему даете, а простой echo Step1 Step2 будет выдавать только одну строку, поэтому вы будете циклически проходить только одно вхождение.

Чтобы избавиться от этого нежелательного поведения, вам придется использовать другие решения.

Одно решение, которое я могу придумать на данный момент, это heredoc :

exec 3<< EOF
Step1
Step2
EOF
while read -r TOTO <&3; do
    PS3="Dummy question ? "
    select CHOICE_MADE in Ans1 Ans2 Ans3; do
        if [[ -n ${CHOICE_MADE} ]]; then
            printf "Choice made: %s\n" "${CHOICE_MADE}"
            break
        fi
    done
done
exec 3>&- ### clean fd 3

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

...