Minimálně pět odpovědí na jednu obecnou otázku.
V závislosti na
- Vyhovuje posix:může fungovat na špatných systémech s obecnými prostředími shellu
- specifické pro bash:pomocí takzvaných bashismů
a pokud chcete
- jednoduchá „v řadě“ otázka/odpověď (obecná řešení)
- pěkně formátovaná rozhraní, jako ncurses nebo více grafických pomocí libgtk nebo libqt...
- použijte výkonnou funkci readline historie
1. Obecná řešení POSIX
Můžete použít read
za ním následuje if ... then ... else
:
printf 'Is this a good question (y/n)? '
read answer
# if echo "$answer" | grep -iq "^y" ;then
if [ "$answer" != "${answer#[Yy]}" ] ;then # this grammar (the #[] operator) means that the variable $answer where any Y or y in 1st position will be dropped if they exist.
echo Yes
else
echo No
fi
(Díky komentáři Adama Katze:Výše uvedený test byl nahrazen testem, který je přenosnější a vyhýbá se jedné vidlici:)
POSIX, ale funkce s jedním klíčem
Pokud ale nechcete, aby uživatel musel stisknout Return , můžete napsat:
(Upraveno: Jak @JonathanLeffler správně navrhuje, šetřím Konfigurace stty by mohla být lepší, než je prostě nutit k příčetnosti .)
printf 'Is this a good question (y/n)? '
old_stty_cfg=$(stty -g)
stty raw -echo ; answer=$(head -c 1) ; stty $old_stty_cfg # Careful playing with stty
if echo "$answer" | grep -iq "^y" ;then
echo Yes
else
echo No
fi
Poznámka: Toto bylo testováno pod sh, bash, ksh, dash a busybox!
Totéž, ale čeká se explicitně na y nebo n :
#/bin/sh
printf 'Is this a good question (y/n)? '
old_stty_cfg=$(stty -g)
stty raw -echo
answer=$( while ! head -c 1 | grep -i '[ny]' ;do true ;done )
stty $old_stty_cfg
if echo "$answer" | grep -iq "^y" ;then
echo Yes
else
echo No
fi
Používání vyhrazených nástrojů
Existuje mnoho nástrojů, které byly vytvořeny pomocí libncurses
, libgtk
, libqt
nebo jiné grafické knihovny. Například pomocí whiptail
:
if whiptail --yesno "Is this a good question" 20 60 ;then
echo Yes
else
echo No
fi
V závislosti na vašem systému může být nutné nahradit whiptail
pomocí jiného podobného nástroje:
dialog --yesno "Is this a good question" 20 60 && echo Yes
gdialog --yesno "Is this a good question" 20 60 && echo Yes
kdialog --yesno "Is this a good question" 20 60 && echo Yes
kde 20
je výška dialogového okna v počtu řádků a 60
je šířka dialogového okna. Všechny tyto nástroje mají téměř stejné syntaxe.
DIALOG=whiptail
if [ -x /usr/bin/gdialog ] ;then DIALOG=gdialog ; fi
if [ -x /usr/bin/xdialog ] ;then DIALOG=xdialog ; fi
...
$DIALOG --yesno ...
2. Specifická řešení Bash
Základní v řadě metoda
read -p "Is this a good question (y/n)? " answer
case ${answer:0:1} in
y|Y )
echo Yes
;;
* )
echo No
;;
esac
Dávám přednost použití case
takže jsem mohl dokonce testovat na yes | ja | si | oui
v případě potřeby...
v řadě pomocí jednoho klíče funkce
Pod bash můžeme zadat délku zamýšleného vstupu pro read
příkaz:
read -n 1 -p "Is this a good question (y/n)? " answer
Pod bash read
příkaz přijímá časový limit parametr, který by mohl být užitečný.
read -t 3 -n 1 -p "Is this a good question (y/n)? " answer
[ -z "$answer" ] && answer="Yes" # if 'yes' have to be default choice
3. Několik triků pro vyhrazené nástroje
Sofistikovanější dialogová okna nad rámec jednoduchých yes - no
účely:
dialog --menu "Is this a good question" 20 60 12 y Yes n No m Maybe
Ukazatel průběhu:
dialog --gauge "Filling the tank" 20 60 0 < <(
for i in {1..100};do
printf "XXX\n%d\n%(%a %b %T)T progress: %d\nXXX\n" $i -1 $i
sleep .033
done
)
Malá ukázka:
#!/bin/sh
while true ;do
[ -x "$(which ${DIALOG%% *})" ] || DIALOG=dialog
DIALOG=$($DIALOG --menu "Which tool for next run?" 20 60 12 2>&1 \
whiptail "dialog boxes from shell scripts" >/dev/tty \
dialog "dialog boxes from shell with ncurses" \
gdialog "dialog boxes from shell with Gtk" \
kdialog "dialog boxes from shell with Kde" ) || exit
clear;echo "Choosed: $DIALOG."
for i in `seq 1 100`;do
date +"`printf "XXX\n%d\n%%a %%b %%T progress: %d\nXXX\n" $i $i`"
sleep .0125
done | $DIALOG --gauge "Filling the tank" 20 60 0
$DIALOG --infobox "This is a simple info box\n\nNo action required" 20 60
sleep 3
if $DIALOG --yesno "Do you like this demo?" 20 60 ;then
AnsYesNo=Yes; else AnsYesNo=No; fi
AnsInput=$($DIALOG --inputbox "A text:" 20 60 "Text here..." 2>&1 >/dev/tty)
AnsPass=$($DIALOG --passwordbox "A secret:" 20 60 "First..." 2>&1 >/dev/tty)
$DIALOG --textbox /etc/motd 20 60
AnsCkLst=$($DIALOG --checklist "Check some..." 20 60 12 \
Correct "This demo is useful" off \
Fun "This demo is nice" off \
Strong "This demo is complex" on 2>&1 >/dev/tty)
AnsRadio=$($DIALOG --radiolist "I will:" 20 60 12 \
" -1" "Downgrade this answer" off \
" 0" "Not do anything" on \
" +1" "Upgrade this anser" off 2>&1 >/dev/tty)
out="Your answers:\nLike: $AnsYesNo\nInput: $AnsInput\nSecret: $AnsPass"
$DIALOG --msgbox "$out\nAttribs: $AnsCkLst\nNote: $AnsRadio" 20 60
done
Více vzorků? Podívejte se na Použití whiptailu k výběru zařízení USB a volič vyměnitelného úložiště USB:USBKeyChooser
5. Použití historie readline
Příklad:
#!/bin/bash
set -i
HISTFILE=~/.myscript.history
history -c
history -r
myread() {
read -e -p '> ' $1
history -s ${!1}
}
trap 'history -a;exit' 0 1 2 3 6
while myread line;do
case ${line%% *} in
exit ) break ;;
* ) echo "Doing something with '$line'" ;;
esac
done
Tím se vytvoří soubor .myscript.history
ve vašem $HOME
adresář, než byste mohli použít příkazy historie readline, jako Nahoru , Dolů , Ctrl +r a další.
Nejjednodušší a nejrozšířenější metoda pro získání uživatelského vstupu do příkazového řádku je read
příkaz. Nejlepší způsob, jak ilustrovat jeho použití, je jednoduchá ukázka:
while true; do
read -p "Do you wish to install this program? " yn
case $yn in
[Yy]* ) make install; break;;
[Nn]* ) exit;;
* ) echo "Please answer yes or no.";;
esac
done
Další metodou, na kterou poukázal Steven Huwig, je Bashova select
příkaz. Zde je stejný příklad s použitím select
:
echo "Do you wish to install this program?"
select yn in "Yes" "No"; do
case $yn in
Yes ) make install; break;;
No ) exit;;
esac
done
S select
nemusíte vstup dezinfikovat – zobrazí dostupné možnosti a vy zadáte číslo odpovídající vašemu výběru. Také se automaticky zacyklí, takže není potřeba while true
smyčka, aby to zkusil znovu, pokud dají neplatný vstup.
Léa Gris také ve své odpovědi předvedla způsob, jak učinit jazyk žádosti agnostickým. Úprava mého prvního příkladu pro lepší obsluhu více jazyků by mohla vypadat takto:
set -- $(locale LC_MESSAGES)
yesexpr="$1"; noexpr="$2"; yesword="$3"; noword="$4"
while true; do
read -p "Install (${yesword} / ${noword})? " yn
if [[ "$yn" =~ $yesexpr ]]; then make install; exit; fi
if [[ "$yn" =~ $noexpr ]]; then exit; fi
echo "Answer ${yesword} / ${noword}."
done
Je zřejmé, že zde zůstávají nepřeložené další komunikační řetězce (Install, Answer), které by bylo třeba řešit v úplnějším překladu, ale i částečný překlad by v mnoha případech pomohl.
Nakonec se prosím podívejte na skvělou odpověď F. Hauriho.
echo "Please enter some input: "
read input_variable
echo "You entered: $input_variable"