Mindestens fünf Antworten für eine allgemeine Frage.
Es hängt davon ab
- posix konform: könnte auf schlechten Systemen mit generischen arbeiten Schale Umgebungen
- Bashspezifisch: mit sogenannten bashismen
und wenn du willst
- einfache "In-Line" -Frage / Antwort (generische Lösungen)
- ziemlich formatierte Schnittstellen, wie Flüche oder grafischer mit libgtk oder libqt ...
- Verwenden Sie die leistungsstarke Readline-Verlaufsfunktion
1. Generische POSIX-Lösungen
Sie können den read
Befehl verwenden, gefolgt von if ... then ... else
:
echo -n "Is this a good question (y/n)? "
read answer
# if echo "$answer" | grep -iq "^y" ;then
if [ "$answer" != "${answer#[Yy]}" ] ;then
echo Yes
else
echo No
fi
(Dank an Adam Katz 'Kommentar : Ersetzte den obigen Test durch einen, der tragbarer ist und eine Gabel vermeidet :)
POSIX, aber Single Key-Funktion
Aber wenn Sie nicht möchten, dass der Benutzer schlagen muss Return, können Sie schreiben:
( Bearbeitet: Wie @JonathanLeffler zu Recht vorschlägt, könnte es besser sein, die Konfiguration von stty zu speichern , als sie einfach zu zwingen, gesund zu werden .)
echo -n "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
Hinweis: Dies wurde unter getestetSch, Bash, ksh, Strich und Busybox!
Gleich, aber explizit warten auf yoder n:
#/bin/sh
echo -n "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
Verwenden dedizierter Tools
Es gibt viele Tools , die mit gebaut wurden libncurses
, libgtk
, libqt
oder andere grafische Bibliotheken. Zum Beispiel mit whiptail
:
if whiptail --yesno "Is this a good question" 20 60 ;then
echo Yes
else
echo No
fi
Abhängig von Ihrem System müssen Sie möglicherweise ein whiptail
anderes ähnliches Tool ersetzen :
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
Dabei 20
ist die Höhe des Dialogfelds in Anzahl der Zeilen und 60
die Breite des Dialogfelds angegeben. Diese Tools haben alle nahezu dieselbe Syntax.
DIALOG=whiptail
if [ -x /usr/bin/gdialog ] ;then DIALOG=gdialog ; fi
if [ -x /usr/bin/xdialog ] ;then DIALOG=xdialog ; fi
...
$DIALOG --yesno ...
2. Bash-spezifische Lösungen
Grundlegende In-Line- Methode
read -p "Is this a good question (y/n)? " answer
case ${answer:0:1} in
y|Y )
echo Yes
;;
* )
echo No
;;
esac
Ich bevorzuge die Verwendung, case
damit ich yes | ja | si | oui
bei Bedarf sogar testen kann ...
im Einklang mit einzelnem Schlüsselmerkmal
Unter bash können wir die Länge der beabsichtigten Eingabe für den read
Befehl angeben :
read -n 1 -p "Is this a good question (y/n)? " answer
Unter bash read
akzeptiert der Befehl einen Timeout- Parameter, der nützlich sein kann.
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. Einige Tricks für spezielle Tools
Anspruchsvollere Dialogfelder, die über einfache yes - no
Zwecke hinausgehen :
dialog --menu "Is this a good question" 20 60 12 y Yes n No m Maybe
Fortschrittsanzeige:
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
)
Kleine Demo:
#!/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
Mehr Probe? Schauen Sie sich die Verwendung von Whiptail für die Auswahl des USB-Geräts und des USB-Wechselspeichers an: USBKeyChooser
5. Verwenden des Readline-Verlaufs
Beispiel:
#!/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
Dadurch wird eine Datei erstellen .myscript.history
in Ihrem $HOME
Verzeichnis, als Sie Readline- Geschichte Befehle, wie nutzen könnten Up, Down, Ctrl+ rund andere.
[yn]
Option präsentieren, die aktivierte Option standardmäßig aktiviert ist, dh[Yn]
standardmäßig "Ja" und[yN]
standardmäßig "Nein". Siehe ux.stackexchange.com/a/40445/43532