2010-04-15 14 views
109

Ho bisogno di leggere un valore dal terminale in uno script bash. Mi piacerebbe essere in grado di fornire un valore predefinito che l'utente può modificare.Leggere una variabile in bash con un valore predefinito

# Please enter your name: Ricardo^ 

In questo script il prompt è "Inserisci il tuo nome:" il valore di default è "Ricardo" e il cursore sarebbe dopo il valore di default. C'è un modo per farlo in uno script bash?

risposta

142

è possibile utilizzare parameter expansion esempio

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

Ho finito per fare qualcosa basato su questo. Lettura in una variabile temporanea 'input' e quindi usando' name = $ {input: - $ name} '. – rmarimon

+26

Questo in realtà non risponde alla domanda. Il valore predefinito dovrebbe essere visualizzato nel prompt. –

+0

e quale sarà 'name = $ {! Input: - $ name}' do? –

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

Impostare il valore predefinito; stampalo; leggi un nuovo valore; se c'è un nuovo valore, usarlo al posto del valore predefinito. C'è (o c'era) qualche variazione tra shell e sistemi su come sopprimere una nuova riga alla fine di un prompt. La notazione '\ c' sembra funzionare su MacOS X 10.6.3 con un bash 3.x, e funziona sulla maggior parte delle varianti di Unix derivate da System V, usando shell Bourne o Korn.

Si noti inoltre che l'utente probabilmente non realizzerà cosa sta succedendo dietro le quinte; i loro nuovi dati sarebbero stati inseriti dopo il nome già presente sullo schermo. Potrebbe essere meglio di formattarlo:

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

'printf' è più portabile di' echo' – ghostdog74

+1

@ ghostdog74: forse così; quelli di noi che hanno imparato la programmazione delle shell più di 25 anni fa hanno difficoltà a capire quali delle nostre pratiche sono ancora rilevanti.Sembra sempre che bash abbia riscritto praticamente tutto. So che printf è stato un po 'come un comando - lo uso molto raramente, anche se (probabilmente - mai?). Ho l'impressione che dovrei stare zitto finché non avrò (ri) imparato Bash. È divertente; il software su cui lavoro ha script di shell che non funzionano bene, ma il problema non sono i bash-isms. Sono stufo di correggere 'if (test -z "$ xxx"); ... ''e altri c gazzismi. –

33

In Bash 4:

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

Questo mostra il nome dopo il prompt come questo:

Please enter your name: Ricardo 

con il cursore alla fine del nome e consente all'utente di modificarlo. L'ultima riga è facoltativa e obbliga il nome al default originale se l'utente cancella l'input o il valore predefinito (inviando un valore null).

+0

Impossibile usare bash4 perché non è standard nelle distribuzioni di debian. Ho bisogno di qualcosa che funzioni senza troppi problemi. – rmarimon

+0

non c'è bisogno dell'ultima riga di codice, basta usare 'name' invece di' input' nel comando 'read'. – RNA

+1

@RNAer: utilizzando la variabile extra, il valore di '$ nome' viene mantenuto se l'utente elimina il valore proposto (e quindi immette una stringa nulla). Tutto dipende da ciò che è necessario. Ho detto tanto nella mia risposta. Hai ragione, però, che avrei potuto essere più esplicito e ho detto che se non si utilizzava la linea opzionale, la variabile avrebbe potuto essere "nome". –

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

echo $NAME 
+1

Ottima risposta! Voglio solo dire che ho avuto problemi con questo, perché non ho visto lo spazio tra "Ricardo" e NAME, ma una volta l'ho capito ... * magia *! Grazie! –

+25

purtroppo -i non è un'opzione valida per OSX 10.7 – undefined

+0

@BrianMortenson È possibile aggiornare bash utilizzando homebrew: http://stackoverflow.com/questions/16416195/how-do-i-upgrade-bash-in-mac-osx -mountain-lion-and-set-it-the-correct-path – antonagestam

10

Codice:

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" 

esempio di esecuzione:

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

Mi piace perché segue la convenzione che vedo in molti script di shell in cui il valore predefinito è tra parentesi quadre prima dei due punti. Grazie!!! – morphatic

-1

Il -e e il parametro -t non lavorano insieme. Ho provato alcune espressioni e il risultato è stato il seguente frammento di codice:

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

La tua risposta non ha molto a che fare con la domanda, vero? ... –

+0

è un modo per aggirare l'utilizzo del parametro -e e -t. questo codeline (-e e -i per il valore di default): leggere -e -p "Inserisci il tuo nome:" -i "Ricardo" NAME non funziona con un countdowntimer (-t) – speefak

+0

Sì, ma questo è non chiesto nella domanda, vero? –

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

per favore aggiungi una spiegazione alla tua risposta. –

9

Ho trovato questa domanda, alla ricerca di un modo di presentare qualcosa di simile:

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

Utilizzando gli esempi di cui sopra ho dedotto questo: -

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 

La speranza che aiuta qualcuno a non dover pensare la logica, se incontrano lo stesso problema

+0

Molto bello. Potrebbe essere persino migliorato un po 'per ripetere la domanda se qualcuno inserisce semplicemente "k" o qualcos'altro rispetto alle scelte date. – erikbwork

+1

Ho appena scritto questo commento seguendo un prurito graffiato. Ora ho una funzione di shell, che include quanto sopra, e io tendo ad usarlo. La shell non sembra circolare bene, quindi cerco di evitarlo. Potrei testare il risultato della mia funzione, e dare un altro tentativo, ma fondamentalmente, sto scrivendo degli strumenti di amministrazione dove le cose potrebbero andare storte, quindi voglio che l'amministratore sia in grado di fermare lo script in modo pulito in qualsiasi momento. – sibaz

6

ho appena usato questo schema, che io preferisco:

read name || name='(nobody)' 
Problemi correlati