Переключатель регистра не работает в Shell

Переключатель регистра не работает в Shell

Я собираюсь использовать gdialogдля приема пользовательского ввода и передачи его для переключения регистра в оболочке. Ниже приведен мой код:

#!/bin/sh


which gdialog 2> /dev/null && DIALOG=gdialog || DIALOG=dialog

end () {
    # rm -f $FILE1 $FILE2 $ERROR
    echo "User pressed cancel!"
exit
}

while true
do
    choice=$($DIALOG --title "Messenger" --menu "Command" 8 35 8 \
    "Date" "Get today's date" \
    "Time" "Get today's time")|| end

    # echo $choice

    case "$choice" in
            "Date")

            MSG="Date is requested"
            echo $MSG
            $DIALOG --yesno "$MSG" 7 20 || end          
     ;;
            "Time")
            MSG="Time is requested!"
            $DIALOG --yesno "$MSG" 7 20 || end          
     ;;
    esac
done

Проблема в том, что выполняется switch case и поток управления достигает первого case или второго case, но строка после объявления MSGпеременной не выполняется. Я собираюсь спросить пользователя, хочет ли он продолжить, используя yes/no gdialog. Что я здесь делаю не так?

решение1

Подстановка команд заменяется стандартным выводом команды. dialog использует stdout для отображения своего пользовательского интерфейса, gdialog, насколько мне известно, вообще его не использует. Оба используют stderr для возврата результата.

Один из способов заставить ваш скрипт работать так, как вы ожидаете, — это поменять местами stdout и stderr в подстановке команд:

choice=$($DIALOG --title "Messenger" --menu "Command" 8 35 8 \
"Date" "Get today's date" \
"Time" "Get today's time" 3>&2 2>&1 1>&3)|| end

решение2

dialogзапишет свой результат в стандартный вывод ошибок, если только вы не прибегнете к обходному пути с перенаправлением или не используете опцию --stdout(потому что, как и любое приложение curses, оно по умолчанию записывает свой вывод в стандартный вывод и сообщает о стандартной ошибке). Вы бы этого не заметили с gdialog, поскольку он записывает свой вывод в другое окно.

Из-за этого, gdialogбудет писатьничегов стандартный вывод и $choiceбудет пустым. Скрипт выполнит case-statement, но не сопоставит ни один из case. Как правило, case-statement должен иметь значение по умолчанию, например,*)чтобы вы могли оставить сообщениетами посмотреть, что происходит.

Это не часть вопроса, нокакчтобы обойти проблему, кажется, ожидается. Скрипт ссылается на gdialog, что, вероятно, является вызовом скрипта zenity(оригинальныйgdialogявляетсядавно прошли). Ни у одной из них нет такой --stdoutвозможности, хотя, вероятно, она существовала еще до появления любой из этих программ (см.запись в журнале изменений от 2000 года). Вы можете обойти это в оболочке, поменяв дескрипторы файлов на стандартный вывод и ошибку. Это также было в примерах сценариев dialog с конца 2000 года, используя предложение Carey Evans (разработчик tn5250):

    Можно захватить вывод из диалога, не используя
    временных файлов вообще, как я сделал в скрипте tn5250 "xt5250":

        исполнитель 3>&1
        XT5250_HOST="`$DIALOG --backtitle "xt5250" --title "Подключиться к хосту" \
          --inputbox "Введите имя или IP-адрес хоста для подключения:" \
          7 60 2>&1 1>&3`"
        рет=$?
        исполнитель 3>&-

    Возможно, вы могли бы рассмотреть возможность использования чего-то вроде этого вместо
    временные файлы. Хитрость с дополнительными fd становится немного сложнее
    хотя читайте.

    > (хотя это всего лишь примеры — сколько работы мне нужно потратить, чтобы сделать их безопасными?)

    Люди _будут_ их копировать и вставлять.

Согласившись с этим, это помогает остановиться и объяснить скрипты. Документация bash помогает здесь, сПеремещение файловых дескрипторов. Этот сценарий

(sh myscript.sh 3>&2 2>&1 1>&3) 2>/dev/null

можно прочитать справа налево как (а) перемещение дескриптора файла 1 (стандартный вывод) до 3, 2 (stderr) до 1, а затем 3 (первоначальностандартный вывод) к 2.

Таким образом, вы можете улучшить свой скрипт, вставив ту же серию изменений в дескрипторы файлов:

3>&2 2>&1 1>&3

в задании choice:

choice=$($DIALOG --title "Messenger" --menu "Command" 8 35 8 \
"Date" "Get today's date" \
"Time" "Get today's time" 3>&2 2>&1 1>&3 )|| end

Дальнейшее чтение:

Связанный контент