Я собираюсь использовать 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
Дальнейшее чтение: