Je suis assez nouveau dans les scripts Shell, mais j'aimerais écrire un script de base dans lequel le fichier bash fera écho à une ligne de texte différente en fonction de la saisie de l'utilisateur. Par exemple, si le script demande à l'utilisateur "Êtes-vous là?" et l'entrée de l'utilisateur est "oui" ou "oui", le script renvoie alors quelque chose comme "hello!". Mais si l'entrée de l'utilisateur est "non" ou "non", le script fera écho à autre chose. Et enfin, si la saisie de l'utilisateur est autre que oui/oui ou non/non, le script renvoie l'écho "répondez oui ou non". Voici ce que j'ai jusqu'à présent:
echo "Are you there?"
read $input
if [ $input == $yes ]; then
echo "Hello!"
Elif [ $input == $no ]]; then
echo "Are you sure?"
else
echo "Please answer yes or no."
fi
Cependant, peu importe l'entrée, je reçois toujours la première réponse ("Bonjour!")
De plus, j'aimerais incorporer du texte à la parole (comme je l'ai fait avec d'autres projets de fichiers bash utilisant festival). Dans d'autres fichiers bash, je l'ai fait de cette façon:
echo "Hello!"
echo "Hello!" | festival --tts
Y a-t-il un moyen d'intégrer cela dans l'invite if then/yes no ci-dessus? Merci d'avance, j'utilise ceci pour créer des fichiers bash simples et m'aider à apprendre.
Le problème principal est ici:
read $input
Dans bash, généralement, $foo
est la valeur de la variable foo
. Ici, vous ne voulez pas la valeur, mais le nom de la variable, donc ça devrait être juste:
read input
De même, dans les tests if
, $yes
et $no
devraient être juste yes
et no
, puisque vous ne voulez que les chaînes yes
et no
.
Vous pouvez utiliser une instruction case
ici, ce qui (IMHO) facilite la réalisation de plusieurs cas en fonction de l'entrée:
case $input in
[Yy]es) # The first character can be Y or y, so both Yes and yes work
echo "Hello!"
echo "Hello!" | festival --tts
;;
[Nn]o) # no or No
echo "Are you sure?"
echo "Are you sure?" | festival --tts
;;
*) # Anything else
echo "Please answer yes or no."
echo "Please answer yes or no." | festival --tts
;;
esac
Vous pouvez encapsuler les deux instructions echo
et l'utilisation de festival
dans une fonction pour éviter de vous répéter:
textAndSpeech ()
{
echo "$@"
echo "$@" | festival --tts
}
case $input in
[Yy]es) # The first character can be Y or y, so both Yes and yes work
textAndSpeech "Hello!"
;;
[Nn]o) # no or No
textAndSpeech "Are you sure?"
;;
*) # Anything else
textAndSpeech "Please answer yes or no."
;;
esac
Avec $input
, bash remplace ceci par sa valeur, qui n'est rien au départ. La commande read
est donc:
read
Et read
enregistre par défaut l’entrée dans la variable REPLY
. Ainsi, vous pouvez, si vous le souhaitez, éliminer la variable input
et utiliser $REPLY
au lieu de $input
.
Regardez également l'instruction select
dans Bash.
TL; DR : corrige les erreurs de syntaxe, vérifie que le test [
contient des variables non vides, et crée une fonction permettant de rediriger tee
en festival
nom__.
En ce qui concerne l'impression sur l'écran et la sortie sur festival
name__, je voudrais personnellement envelopper le script dans une fonction et diriger le tout vers festival
name__, avec tee
entre les deux (ce qui envoie du texte à la fois à l'écran et au tuyau).
Il y a cependant trois problèmes de syntaxe à résoudre:
read $input
devrait être read input
. La variable de déréférence de symbole $
dans les scripts de shell (c.-à-d., Elle sera remplacée par $input
par ce que contient input
name__).yes
et no
name__. Ce que vous devriez faire est une comparaison de chaînes: [ "$input" == "yes" ]
]]
supplémentaire dans Elif
name__Quant à savoir pourquoi vous obtenez Hello!
tout le temps, c’est exactement à cause des deux premiers points. Avant read $input
, la variable input
n'existait pas. Vous ne faites donc que read
(c'est-à-dire que la variable inexistante $input
est déréférencée dans une chaîne vide, ne laissant que la commande read
name__. Ainsi, tout ce que vous tapez est stocké dans la variable REPLY
qui correspond à ce que read
utilise quand aucun nom de variable n'a été donné. Et comme la variable yes
n'existe pas, elle est également remplacée par une chaîne vide. Ainsi, en réalité, [ $input == $yes ]
est traité comme [ "" == "" ]
qui est toujours vrai.
$ [ $nonexistent == $anothernonexistent ] && echo "Success"
Success
Le script corrigé doit être comme suit:
#!/bin/bash
main(){
read -p "Are you there?" input
if [ "$input" == "yes" ]; then
echo "Hello!"
Elif [ "$input" == "no" ]; then
echo "Are you sure?"
else
echo "Please answer yes or no."
fi
}
main | tee /dev/tty | festival --tts
N'oubliez pas de citez les variables et lisez-le sur différence entre =
et ==
dans la commande de test .
Une troisième approche serait d’affecter une variable commune à chaque cas et d’agir en fin de compte sur cette variable. Je ne sais pas à quel point cette approche est courante dans bash, mais dans d'autres langages de programmation, elle est assez standard.
Également shopt -s nocasematch
en conjonction avec [[
pour la comparaison de chaînes sans distinction de casse.
Avec cela aussi, YES
et NO
sont considérés comme une entrée valide.
#!/bin/bash
shopt -s nocasematch
read -p "Are you there?" input
if [[ "$input" == "yes" ]]; then
msg="Hello!"
Elif [[ "$input" == "no" ]]; then
msg="Are you sure?"
else
msg="Please answer yes or no."
fi
echo $msg
echo $msg | festival --tts