Ich möchte die Eingabe in einem Shell-Skript anhalten und den Benutzer zur Auswahl auffordern. Die Standardfrage vom Typ "Ja, Nein oder Abbrechen". Wie mache ich das mit einer typischen Bash-Eingabeaufforderung?
Die einfachste und am weitesten verbreitete Methode, um Benutzereingaben an einer Shell-Eingabeaufforderung abzurufen, ist der Befehl read
. Der beste Weg, seine Verwendung zu veranschaulichen, ist eine einfache Demonstration:
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
Eine andere Methode, auf die Steven Huwig hingewiesen hat, ist der Befehl select
von Bash. Im folgenden Beispiel wird select
verwendet:
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
Mit select
müssen Sie die Eingabe nicht bereinigen - es werden die verfügbaren Auswahlmöglichkeiten angezeigt, und Sie geben eine Zahl ein, die Ihrer Auswahl entspricht. Es wird auch automatisch wiederholt, sodass keine while true
-Schleife erforderlich ist, um einen erneuten Versuch durchzuführen, wenn ungültige Eingaben gemacht werden.
Lesen Sie auch das ausgezeichnete Antwort von F. Hauri.
Es hängt davon ab
und wenn du willst
Sie können den Befehl read
gefolgt von _if ... then ... else
_ verwenden:
_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's Kommentar : Ersetzte den obigen Test durch einen, der tragbarer ist und eine Gabel vermeidet :)
Aber wenn Sie nicht möchten, dass der Benutzer trifft ReturnSie könnten schreiben:
( Bearbeitet: Wie @JonathanLeffler zu Recht andeutet, könnte es besser sein, die Konfiguration von stty zu speichern, als sie einfach zu erzwingen gesund .)
_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 getestet unter sh , bash , ksh , Bindestrich und Busybox !
Gleich, aber explizit abwarten y oder 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
_
Es gibt viele Tools, die mit libncurses
, libgtk
, libqt
oder anderen grafischen Bibliotheken erstellt wurden. 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 whiptail
durch ein 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 ist _20
_ die Höhe des Dialogfelds in Zeilen und _60
_ die Breite des Dialogfelds. Diese Werkzeuge haben alle fast die gleiche Syntax.
_DIALOG=whiptail
if [ -x /usr/bin/gdialog ] ;then DIALOG=gdialog ; fi
if [ -x /usr/bin/xdialog ] ;then DIALOG=xdialog ; fi
...
$DIALOG --yesno ...
_
_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 von case
, damit ich bei Bedarf sogar auf _yes | ja | si | oui
_ testen kann ...
Unter bash können wir die Länge der beabsichtigten Eingabe für den Befehl read
angeben:
_read -n 1 -p "Is this a good question (y/n)? " answer
_
Unter Bash akzeptiert der Befehl read
einen Timeout-Parameter , was 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
_
Anspruchsvollere Dialogfelder jenseits einfacher yes - no
Zwecke:
_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 Verwenden von Whiptail zur Auswahl des USB-Geräts und SB-Wechselspeicherselektor: USBKeyChooser an
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 _.myscript.history
_ in Ihrem _$HOME
_ -Verzeichnis erstellt, die Sie beispielsweise mit den Verlaufsbefehlen von readline verwenden können Up, Down, Ctrl+r und andere.
echo "Please enter some input: "
read input_variable
echo "You entered: $input_variable"
Sie können den eingebauten Befehl read verwenden. Verwenden Sie die Option -p
, um den Benutzer zu einer Frage aufzufordern.
Seit BASH4 können Sie jetzt -i
verwenden, um eine Antwort vorzuschlagen, sodass der Benutzer nur return
drücken muss, um sie einzugeben:
read -e -p "Enter the path to the file: " -i "/usr/local/etc/" FILEPATH
echo $FILEPATH
(Denken Sie jedoch daran, die Option "readline" -e
zu verwenden, um die Zeilenbearbeitung mit den Pfeiltasten zu ermöglichen.)
Wenn Sie eine Ja/Nein-Logik wünschen, können Sie Folgendes tun:
read -e -p "
List the content of your home dir ? [Y/n] " YN
[[ $YN == "y" || $YN == "Y" || $YN == "" ]] && ls -la ~/
Bash hat zu diesem Zweck select .
select result in Yes No Cancel
do
echo $result
done
read -p "Are you alright? (y/n) " RESP
if [ "$RESP" = "y" ]; then
echo "Glad to hear it"
else
echo "You need more bash programming"
fi
Folgendes habe ich zusammengestellt:
#!/bin/sh
promptyn () {
while true; do
read -p "$1 " yn
case $yn in
[Yy]* ) return 0;;
[Nn]* ) return 1;;
* ) echo "Please answer yes or no.";;
esac
done
}
if promptyn "is the sky blue?"; then
echo "yes"
else
echo "no"
fi
Ich bin ein Anfänger, also nimm das mit einem Körnchen Salz, aber es scheint zu funktionieren.
inquire () {
echo -n "$1 [y/n]? "
read answer
finish="-1"
while [ "$finish" = '-1' ]
do
finish="1"
if [ "$answer" = '' ];
then
answer=""
else
case $answer in
y | Y | yes | YES ) answer="y";;
n | N | no | NO ) answer="n";;
*) finish="-1";
echo -n 'Invalid response -- please reenter:';
read answer;;
esac
fi
done
}
... other stuff
inquire "Install now?"
...
do_xxxx=y # In batch mode => Default is Yes
[[ -t 0 ]] && # If TTY => Prompt the question
read -n 1 -p $'\e[1;32m
Do xxxx? (Y/n)\e[0m ' do_xxxx # Store the answer in $do_xxxx
if [[ $do_xxxx =~ ^(y|Y|)$ ]] # Do if 'y' or 'Y' or empty
then
xxxx
fi
[[ -t 0 ]] && read ...
=> Befehl read
aufrufen, wenn TTYread -n 1
=> Warten Sie auf ein Zeichen$'\e[1;32m ... \e[0m '
=> Grün drucken[[ $do_xxxx =~ ^(y|Y|)$ ]]
=> Bash Regexdo_xxxx=y
[[ -t 0 ]] && { # Timeout 5 seconds (read -t 5)
read -t 5 -n 1 -p $'\e[1;32m
Do xxxx? (Y/n)\e[0m ' do_xxxx || # read 'fails' on timeout
do_xxxx=n ; } # Timeout => answer No
if [[ $do_xxxx =~ ^(y|Y|)$ ]]
then
xxxx
fi
Der einfachste Weg, dies mit der geringsten Anzahl von Zeilen zu erreichen, ist wie folgt:
read -p "<Your Friendly Message here> : y/n/cancel" CONDITION;
if [ "$CONDITION" == "y" ]; then
# do something here!
fi
Das if
ist nur ein Beispiel: Es liegt an Ihnen, wie Sie mit dieser Variablen umgehen.
Verwenden Sie den Befehl read
:
echo Would you like to install? "(Y or N)"
read x
# now check if $x is "y"
if [ "$x" = "y" ]; then
# do something here!
fi
und dann all die anderen Sachen, die du brauchst
Diese Lösung liest ein einzelnes Zeichen und ruft bei einer Ja-Antwort eine Funktion auf.
read -p "Are you sure? (y/n) " -n 1
echo
if [[ $REPLY =~ ^[Yy]$ ]]; then
do_something
fi
read -e -p "Enter your choice: " choice
Mit der Option -e
kann der Benutzer die Eingabe mit den Pfeiltasten bearbeiten.
Wenn Sie einen Vorschlag als Eingabe verwenden möchten:
read -e -i "yes" -p "Enter your choice: " choice
Die Option -i
druckt eine suggestive Eingabe.
Sie können die Standardeinstellung REPLY
für read
verwenden, in Kleinbuchstaben konvertieren und mit einer Reihe von Variablen mit einem Ausdruck vergleichen.
Das Skript unterstützt auch ja
/si
/oui
read -rp "Do you want a demo? [y/n/c] "
[[ ${REPLY,,} =~ ^(c|cancel)$ ]] && { echo "Selected Cancel"; exit 1; }
if [[ ${REPLY,,} =~ ^(y|yes|j|ja|s|si|o|oui)$ ]]; then
echo "Positive"
fi
Tut mir leid, dass ich auf so einem alten Beitrag gepostet habe. Vor einigen Wochen hatte ich ein ähnliches Problem, in meinem Fall brauchte ich eine Lösung, die auch in einem Online-Installationsskript funktioniert, zB: curl -Ss https://raw.github.com/_____/installer.sh | bash
Die Verwendung von read yesno < /dev/tty
funktioniert gut für mich:
echo -n "These files will be uploaded. Is this ok? (y/n) "
read yesno < /dev/tty
if [ "x$yesno" = "xy" ];then
# Yes
else
# No
fi
Hoffe das hilft jemandem.
Hier ist ein längerer, aber wiederverwendbarer und modularer Ansatz:
0
= yes und 1
= no zurückzsh
und bash
.Beachten Sie, dass das N
groß geschrieben ist. Hier wird die Eingabetaste gedrückt, wobei die Standardeinstellung übernommen wird:
$ confirm "Show dangerous command" && echo "rm *"
Show dangerous command [y/N]?
Beachten Sie auch, dass [y/N]?
automatisch angehängt wurde. Die Standardeinstellung "nein" wird akzeptiert, daher wird nichts zurückgemeldet.
Wiederholen Sie die Eingabeaufforderung, bis eine gültige Antwort vorliegt:
$ confirm "Show dangerous command" && echo "rm *"
Show dangerous command [y/N]? X
Show dangerous command [y/N]? y
rm *
Beachten Sie, dass das Y
groß geschrieben wird:
$ confirm_yes "Show dangerous command" && echo "rm *"
Show dangerous command [Y/n]?
rm *
Oben habe ich einfach die Eingabetaste gedrückt, sodass der Befehl ausgeführt wurde.
y
oder n
$ get_yes_keypress "Here you cannot press enter. Do you like this [y/n]? "
Here you cannot press enter. Do you like this [y/n]? k
Here you cannot press enter. Do you like this [y/n]?
Here you cannot press enter. Do you like this [y/n]? n
$ echo $?
1
Hier wurde 1
oder false zurückgegeben. Beachten Sie, dass Sie bei dieser niedrigeren Funktion Ihre eigene [y/n]?
Eingabeaufforderung angeben müssen.
# Read a single char from /dev/tty, prompting with "$*"
# Note: pressing enter will return a null string. Perhaps a version terminated with X and then remove it in caller?
# See https://unix.stackexchange.com/a/367880/143394 for dealing with multi-byte, etc.
function get_keypress {
local REPLY IFS=
>/dev/tty printf '%s' "$*"
[[ $ZSH_VERSION ]] && read -rk1 # Use -u0 to read from STDIN
# See https://unix.stackexchange.com/q/383197/143394 regarding '\n' -> ''
[[ $BASH_VERSION ]] && </dev/tty read -rn1
printf '%s' "$REPLY"
}
# Get a y/n from the user, return yes=0, no=1 enter=$2
# Prompt using $1.
# If set, return $2 on pressing enter, useful for cancel or defualting
function get_yes_keypress {
local Prompt="${1:-Are you sure [y/n]? }"
local enter_return=$2
local REPLY
# [[ ! $Prompt ]] && Prompt="[y/n]? "
while REPLY=$(get_keypress "$Prompt"); do
[[ $REPLY ]] && printf '\n' # $REPLY blank if user presses enter
case "$REPLY" in
Y|y) return 0;;
N|n) return 1;;
'') [[ $enter_return ]] && return "$enter_return"
esac
done
}
# Credit: http://unix.stackexchange.com/a/14444/143394
# Prompt to confirm, defaulting to NO on <enter>
# Usage: confirm "Dangerous. Are you sure?" && rm *
function confirm {
local Prompt="${*:-Are you sure} [y/N]? "
get_yes_keypress "$Prompt" 1
}
# Prompt to confirm, defaulting to YES on <enter>
function confirm_yes {
local Prompt="${*:-Are you sure} [Y/n]? "
get_yes_keypress "$Prompt" 0
}
Um ein ncurses-ähnliches Eingabefeld zu erhalten, verwenden Sie den folgenden Befehl :
#!/bin/bash
if (dialog --title "Message" --yesno "Want to do something risky?" 6 25)
# message box will have the size 25x6 characters
then
echo "Let's do something risky"
# do something risky
else
echo "Let's stay boring"
fi
Das Dialogpaket wird standardmäßig mindestens mit SUSE Linux installiert.
Mir ist aufgefallen, dass niemand eine Antwort gepostet hat, die ein mehrzeiliges Echo-Menü für so einfache Benutzereingaben zeigt.
#!/bin/bash
function ask_user() {
echo -e "
#~~~~~~~~~~~~#
| 1.) Yes |
| 2.) No |
| 3.) Quit |
#~~~~~~~~~~~~#\n"
read -e -p "Select 1: " choice
if [ "$choice" == "1" ]; then
do_something
Elif [ "$choice" == "2" ]; then
do_something_else
Elif [ "$choice" == "3" ]; then
clear && exit 0
else
echo "Please select 1, 2, or 3." && sleep 3
clear && ask_user
fi
}
ask_user
Diese Methode wurde in der Hoffnung veröffentlicht, dass jemand sie nützlich und zeitsparend findet.
Multiple-Choice-Version:
ask () { # $1=question $2=options
# set REPLY
# options: x=..|y=..
while $(true); do
printf '%s [%s] ' "$1" "$2"
stty cbreak
REPLY=$(dd if=/dev/tty bs=1 count=1 2> /dev/null)
stty -cbreak
test "$REPLY" != "$(printf '\n')" && printf '\n'
(
IFS='|'
for o in $2; do
if [ "$REPLY" = "${o%%=*}" ]; then
printf '\n'
break
fi
done
) | grep ^ > /dev/null && return
done
}
Beispiel:
$ ask 'continue?' 'y=yes|n=no|m=maybe'
continue? [y=yes|n=no|m=maybe] g
continue? [y=yes|n=no|m=maybe] k
continue? [y=yes|n=no|m=maybe] y
$
Es setzt REPLY
auf y
(innerhalb des Skripts).
Inspiriert von den Antworten von @Mark und @Myrddin habe ich diese Funktion für eine universelle Eingabeaufforderung erstellt
uniprompt(){
while true; do
echo -e "$1\c"
read opt
array=($2)
case "${array[@]}" in *"$opt"*) eval "$3=$opt";return 0;; esac
echo -e "$opt is not a correct value\n"
done
}
benutze es so:
unipromtp "Select an option: (a)-Do one (x)->Do two (f)->Do three : " "a x f" selection
echo "$selection"
allgemeiner wäre:
function menu(){
title="Question time"
Prompt="Select:"
options=("Yes" "No" "Maybe")
echo "$title"
PS3="$Prompt"
select opt in "${options[@]}" "Quit/Cancel"; do
case "$REPLY" in
1 ) echo "You picked $opt which is option $REPLY";;
2 ) echo "You picked $opt which is option $REPLY";;
3 ) echo "You picked $opt which is option $REPLY";;
$(( ${#options[@]}+1 )) ) clear; echo "Goodbye!"; exit;;
*) echo "Invalid option. Try another one.";continue;;
esac
done
return
}
Ein einfacher Weg dies zu tun ist mit xargs -p
oder gnu parallel --interactive
.
Ich mag das Verhalten von xargs etwas besser, weil es jeden Befehl direkt nach der Eingabeaufforderung ausführt, wie andere interaktive Unix-Befehle, anstatt die Yesses zu sammeln, die am Ende ausgeführt werden sollen. (Sie können die Tastenkombination Strg-C drücken, nachdem Sie die gewünschten Schritte ausgeführt haben.)
z.B.,
echo *.xml | xargs -p -n 1 -J {} mv {} backup/
Als Freund eines einzeiligen Befehls habe ich Folgendes verwendet:
while [ -z $Prompt ]; do read -p "Continue (y/n)?" choice;case "$choice" in y|Y ) Prompt=true; break;; n|N ) exit 0;; esac; done; Prompt=;
Geschriebene Langform, es funktioniert so:
while [ -z $Prompt ];
do read -p "Continue (y/n)?" choice;
case "$choice" in
y|Y ) Prompt=true; break;;
n|N ) exit 0;;
esac;
done;
Prompt=;
Ich habe die case
-Anweisung in einem solchen Szenario einige Male verwendet. Die Verwendung der case -Anweisung ist ein guter Weg, um dies zu erreichen. Eine while
-Schleife, die den case
-Block kapselt und eine boolesche Bedingung verwendet, kann implementiert werden, um noch mehr Kontrolle über das Programm zu behalten und viele andere Anforderungen zu erfüllen. Nachdem alle Bedingungen erfüllt sind, kann ein break
verwendet werden, das die Steuerung an den Hauptteil des Programms zurückgibt. Um andere Bedingungen zu erfüllen, können natürlich Bedingungsanweisungen zu den Kontrollstrukturen hinzugefügt werden: case
Anweisung und mögliche while
Schleife.
Beispiel für die Verwendung einer case
-Anweisung zur Erfüllung Ihrer Anforderung
#! /bin/sh
# For potential users of BSD, or other systems who do not
# have a bash binary located in /bin the script will be directed to
# a bourne-Shell, e.g. /bin/sh
# NOTE: It would seem best for handling user entry errors or
# exceptions, to put the decision required by the input
# of the Prompt in a case statement (case control structure),
echo Would you like us to perform the option: "(Y|N)"
read inPut
case $inPut in
# echoing a command encapsulated by
# backticks (``) executes the command
"Y") echo `Do something crazy`
;;
# depending on the scenario, execute the other option
# or leave as default
"N") echo `execute another option`
;;
esac
exit
Ich schlage vor, Sie verwenden Sie den Dialog ...
Linux-Lehrling: Verbessern von Bash-Shell-Skripten mithilfe des Dialogfelds
Der Befehl dialog ermöglicht die Verwendung von Fensterrahmen in Shell-Skripten, um deren Verwendung interaktiver zu gestalten.
es ist einfach und benutzerfreundlich. Es gibt auch eine Gnome-Version namens gdialog, die die exakt gleichen Parameter verwendet, aber den GUI-Stil auf X zeigt.
Als Antwort auf andere:
Sie müssen in BASH4 keine Groß-/Kleinschreibung angeben. Verwenden Sie einfach das ',', um var in Kleinbuchstaben zu schreiben. Ich mag es auch nicht, Code innerhalb des Leseblocks zu platzieren, das Ergebnis zu erhalten und außerhalb des Leseblocks IMO damit umzugehen. Fügen Sie auch ein 'q' zum Beenden von IMO ein. Zum Schluss, warum 'yes' eingeben, einfach -n1 verwenden und die Taste y drücken.
Beispiel: Der Benutzer kann y/n und auch q drücken, um das Programm zu beenden.
ans=''
while true; do
read -p "So is MikeQ the greatest or what (y/n/q) ?" -n1 ans
case ${ans,,} in
y|n|q) break;;
*) echo "Answer y for yes / n for no or q for quit.";;
esac
done
echo -e "\nAnswer = $ans"
if [[ "${ans,,}" == "q" ]] ; then
echo "OK Quitting, we will assume that he is"
exit 0
fi
if [[ "${ans,,}" == "y" ]] ; then
echo "MikeQ is the greatest!!"
else
echo "No? MikeQ is not the greatest?"
fi
#!/usr/bin/env bash
@confirm() {
local message="$*"
local result=''
echo -n "> $message (Yes/No/Cancel) " >&2
while [ -z "$result" ] ; do
read -s -n 1 choice
case "$choice" in
y|Y ) result='Y' ;;
n|N ) result='N' ;;
c|C ) result='C' ;;
esac
done
echo $result
}
case $(@confirm 'Confirm?') in
Y ) echo "Yes" ;;
N ) echo "No" ;;
C ) echo "Cancel" ;;
esac
#!/usr/bin/env bash
@confirm() {
local message="$*"
local result=3
echo -n "> $message (y/n) " >&2
while [[ $result -gt 1 ]] ; do
read -s -n 1 choice
case "$choice" in
y|Y ) result=0 ;;
n|N ) result=1 ;;
esac
done
return $result
}
if @confirm 'Confirm?' ; then
echo "Yes"
else
echo "No"
fi
yn() {
if [[ 'y' == `read -s -n 1 -p "[y/n]: " Y; echo $Y` ]];
then eval $1;
else eval $2;
fi }
yn 'echo yes' 'echo no'
yn 'echo absent no function works too!'