2010-04-15 4 views
109

J'ai besoin de lire une valeur du terminal dans un script bash. Je voudrais pouvoir fournir une valeur par défaut que l'utilisateur peut changer.Lire une variable dans bash avec une valeur par défaut

# Please enter your name: Ricardo^ 

Dans ce script l'invite est « S'il vous plaît entrer votre nom: » la valeur par défaut est « Ricardo » et le curseur serait après la valeur par défaut. Existe-t-il un moyen de le faire dans un script bash?

Répondre

142

vous pouvez utiliser parameter expansion par exemple

read -p "Enter: " name 
name=${name:-Richard} 
echo $name 
+4

J'ai fini par faire quelque chose en fonction de cela. Lire dans une variable temp 'input' et ensuite utiliser' name = $ {input: - $ name} '. – rmarimon

+26

Cela ne répond pas réellement à la question. La valeur par défaut devrait être affichée dans l'invite. –

+0

et que va faire 'name = $ {! Input: - $ name}'? –

3
name=Ricardo 
echo "Please enter your name: $name \c" 
read newname 
[ -n "$newname" ] && name=$newname 

Définir la valeur par défaut; imprime le; lire une nouvelle valeur; s'il y a une nouvelle valeur, utilisez-la à la place de la valeur par défaut. Il existe (ou existait) des variations entre les shells et les systèmes sur la façon de supprimer un retour à la ligne à la fin d'une invite. La notation '\ c' semble fonctionner sur MacOS X 10.6.3 avec un bash 3.x, et fonctionne sur la plupart des variantes d'Unix dérivées de System V, en utilisant des shells Bourne ou Korn.

Notez également que l'utilisateur ne réaliserait probablement pas ce qui se passe dans les coulisses; leurs nouvelles données seraient entrées après le nom déjà affiché à l'écran. Il pourrait être préférable de le formater:

echo "Please enter your name ($name): \c" 
+0

'printf' est plus portable que' echo' – ghostdog74

+1

@ ghostdog74: peut-être ainsi; Ceux d'entre nous qui ont appris la programmation coquille il y a plus de 25 ans ont du mal à déterminer lesquelles de nos pratiques sont toujours pertinentes.Il semble de plus en plus que bash a réécrit à peu près tout. Je sais que printf a été utilisé comme commande - je l'utilise très rarement (probablement - jamais?). J'ai l'impression que je devrais me taire jusqu'à ce que j'ai (ré) appris bash. C'est drôle. le logiciel sur lequel je travaille a des scripts shell qui ne fonctionnent pas bien - mais le problème n'est pas bash-isms. J'en ai juste marre de fixer '' if (test -z "$ xxx"); ... "et d'autres césarismes. –

33

Bash 4:

name="Ricardo" 
read -e -i "$name" -p "Please enter your name: " input 
name="${input:-$name}" 

Affiche le nom à l'invite comme ceci:

Please enter your name: Ricardo 

avec le curseur à la fin du nom et permet à l'utilisateur de le modifier. La dernière ligne est facultative et force le nom à être le nom par défaut si l'utilisateur efface l'entrée ou la valeur par défaut (en soumettant une valeur nulle).

+0

Impossible d'utiliser bash4 car il est non standard dans les distributions debian. J'ai besoin de quelque chose qui fonctionnera sans trop de tracas. – rmarimon

+0

pas besoin de la dernière ligne de code, utilisez juste 'name' au lieu de' input' dans la commande 'read'. – RNA

+1

@RNAer: En utilisant la variable supplémentaire, la valeur de $ nom est préservée si l'utilisateur supprime la valeur proposée (et donc introduit une chaîne vide). Tout dépend de ce que votre besoin est. Je l'ai dit autant dans ma réponse. Vous avez raison, cependant, que j'aurais pu être plus explicite et que si la ligne optionnelle n'était pas utilisée, la variable aurait pu être 'nom'. –

110
read -e -p "Enter Your Name:" -i "Ricardo" NAME 

echo $NAME 
+1

Bonne réponse! Je veux juste mentionner que j'avais des problèmes avec ça, parce que je n'ai pas vu l'espace entre "Ricardo" et NAME, mais une fois j'ai compris ça ... * magic *! Je vous remercie! –

+25

malheureusement -i est pas une option valide pour OSX 10.7 – undefined

+0

@BrianMortenson Vous pouvez mettre à jour bash en utilisant homebrew: http://stackoverflow.com/questions/16416195/how-do-i-upgrade-bash-in-mac-osx -mountain-lion-et-set-it-the-correct-path – antonagestam

10

code:

IN_PATH_DEFAULT="/tmp/input.txt" 
read -p "Please enter IN_PATH [$IN_PATH_DEFAULT]: " IN_PATH 
IN_PATH="${IN_PATH:-$IN_PATH_DEFAULT}" 

OUT_PATH_DEFAULT="/tmp/output.txt" 
read -p "Please enter OUT_PATH [$OUT_PATH_DEFAULT]: " OUT_PATH 
OUT_PATH="${OUT_PATH:-$OUT_PATH_DEFAULT}" 

echo "Input: $IN_PATH Output: $OUT_PATH" 

run Exemple:

Please enter IN_PATH [/tmp/input.txt]: 
Please enter OUT_PATH [/tmp/output.txt]: ~/out.txt 
Input: /tmp/input.txt Output: ~/out.txt 
+0

J'aime ça parce qu'il suit la convention que je vois dans beaucoup de scripts shell où la valeur par défaut est entre crochets avant les deux-points. Merci!!! – morphatic

-1

Le paramètre -e et -t ne fonctionne pas ensemble. J'ai essayé quelques expressions et le résultat a été l'extrait de code suivant:

QMESSAGE="SHOULD I DO YES OR NO" 
YMESSAGE="I DO" 
NMESSAGE="I DO NOT" 
FMESSAGE="PLEASE ENTER Y or N" 
COUNTDOWN=2 
DEFAULTVALUE=n 
#----------------------------------------------------------------# 
function REQUEST() 
{ 
read -n1 -t$COUNTDOWN -p "$QMESSAGE ? Y/N " INPUT 
    INPUT=${INPUT:-$DEFAULTVALUE} 
    if [ "$INPUT" = "y" -o "$INPUT" = "Y" ] ;then 
     echo -e "\n$YMESSAGE\n" 
     #COMMANDEXECUTION 
    elif [ "$INPUT" = "n" -o "$INPUT" = "N" ] ;then 
     echo -e "\n$NMESSAGE\n" 
     #COMMANDEXECUTION 
    else 
     echo -e "\n$FMESSAGE\n" 
    REQUEST 
    fi 
} 
REQUEST 
+0

Votre réponse n'a pas grand chose à voir avec la question, a-t-elle? ... –

+0

c'est un travail pour utiliser le paramètre -e et -t. ce codeline (-e et -i pour la valeur par défaut): lire -e -p "Entrez votre nom:" -i "Ricardo" NOM ne fonctionne pas avec un countdowntimer (t) – speefak

+0

Ouais mais c'est pas demandé dans la question, n'est-ce pas? –

0
#Script for calculating various values in MB 
echo "Please enter some input: " 
read input_variable 
echo $input_variable | awk '{ foo = $1/1024/1024 ; print foo "MB" }' 
+3

s'il vous plaît ajouter une explication à votre réponse. –

9

Je trouve cette question, à la recherche d'une façon de présenter quelque chose comme:

Something interesting happened. Proceed [Y/n/q]: 

En utilisant les exemples ci-dessus, je déduisis ceci: -

echo -n "Something interesting happened. " 
DEFAULT="y" 
read -e -p "Proceed [Y/n/q]:" PROCEED 
# adopt the default, if 'enter' given 
PROCEED="${PROCEED:-${DEFAULT}}" 
# change to lower case to simplify following if 
PROCEED="${PROCEED,,}" 
# condition for specific letter 
if [ "${PROCEED}" == "q" ] ; then 
    echo "Quitting" 
    exit 
# condition for non specific letter (ie anything other than q/y) 
# if you want to have the active 'y' code in the last section 
elif [ "${PROCEED}" != "y" ] ; then 
    echo "Not Proceeding" 
else 
    echo "Proceeding" 
    # do proceeding code in here 
fi 

Espérons que cela aide quelqu'un à ne pas avoir à réfléchir à la logique, s'ils rencontrent le même problème

+0

Très bien. Il pourrait même être amélioré un peu pour répéter la question si quelqu'un entre juste "k" ou autre chose que les choix donnés. – erikbwork

+1

Je viens d'écrire ce commentaire suite à un grattage gratté. J'ai maintenant une fonction shell, qui inclut ce qui précède, et j'ai tendance à l'utiliser. Shell ne semble pas boucler bien, alors j'essaie de l'éviter. Je pourrais tester le résultat de ma fonction, et essayer encore une fois, mais fondamentalement, j'écris des outils d'administration où les choses pourraient mal se passer, donc je veux que l'administrateur soit capable d'arrêter proprement le script à tout moment. – sibaz

6

J'ai juste utilisé ce modèle, que je préfère:

read name || name='(nobody)' 
Questions connexes