Leggi una variabile in bash con un valore predefinito


192

Ho bisogno di leggere un valore dal terminale in uno script bash. Vorrei essere in grado di fornire un valore predefinito che l'utente può modificare.

# Please enter your name: Ricardo^

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

Risposte:


280

è possibile utilizzare l' espansione dei parametri ad es

read -p "Enter your name [Richard]: " name
name=${name:-Richard}
echo $name

Includere il valore predefinito nel prompt tra parentesi è una convenzione abbastanza comune


7
Ho finito per fare qualcosa basato su questo. Lettura in una variabile temporanea inpute quindi utilizzo name=${input:-$name}.
Ricardo Marimon,

41
Questo in realtà non risponde alla domanda. Il valore predefinito dovrebbe essere visualizzato nel prompt.
Dr. Person Person II,

3
e cosa farà name=${!input:-$name}?
Harry Lee,

8
@ Dr.PersonPersonII - potresti aggiungere il valore predefinito facendo qualcosa del genere: read -p "Inserisci il nome host remoto [$ remote_host_default]:" remote_host remote_host = $ {host_host: - $ remote_host_default}
Dobler

5
$1diventa${1:-some_default_string}
ThorSummoner il

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

echo $NAME

1
Bella risposta! Voglio solo menzionare che stavo avendo problemi con esso, perché non ho visto lo spazio tra "Ricardo" e NAME, ma una volta l'ho capito .... magia ! Grazie!
Mikkél,

40
sfortunatamente -i non è un'opzione valida per OSX 10.7
non definito il

3
@BrianMortenson È possibile aggiornare bash utilizzando homebrew: stackoverflow.com/questions/16416195/...
antonagestam

2
Questa risposta mostra come farlo funzionare su OS X (Bash 3.x): stackoverflow.com/questions/22634065/…
Christoph Petschnig,

3
Basta notare che -esembra essere obbligatorio per consentire -ieffettivamente di lavorare
MestreLion,

49

In Bash 4:

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

Questo visualizza il nome dopo il prompt in questo modo:

Please enter your name: Ricardo

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


Non è possibile utilizzare bash4 perché non è standard nelle distribuzioni debian. Ho bisogno di qualcosa che funzioni senza troppi problemi.
Ricardo Marimon,

1
non è necessario per l'ultima riga di codice, basta usare nameinvece inputnel readcomando.
RNA

2
@RNAer: utilizzando la variabile extra, il valore di $nameviene preservato se l'utente elimina il valore proposto (e quindi inserisce una stringa nulla). Tutto dipende da quale sia il tuo bisogno. Ho detto altrettanto nella mia risposta. Hai ragione, però, che avrei potuto essere più esplicito e dire che se non fosse stata utilizzata la linea opzionale, la variabile avrebbe potuto essere name.
In pausa fino a nuovo avviso.

1
@DennisWilliamson: hai ragione. È una buona pratica se è quello che si desidera.
RNA

16

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"

Esecuzione di esempio:

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

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!!!
morfico

16

Ho trovato questa domanda, cercando un modo per presentare qualcosa come:

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

Usando gli esempi 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

Spero che aiuti qualcuno a non dover pensare alla logica, se incontrano lo stesso problema


Molto bella. Potrebbe anche essere leggermente migliorato per ripetere la domanda se qualcuno inserisce semplicemente "k" o qualcos'altro rispetto alle scelte fornite.
erikbwork,

1
Ho appena scritto questo commento dopo un prurito graffiato. Ora ho una funzione shell, che include quanto sopra, e tendo ad usarla. Shell non sembra funzionare bene, quindi cerco di evitarlo. Potrei testare il risultato dalla mia funzione e fare un altro tentativo, ma fondamentalmente sto scrivendo strumenti di amministrazione in cui le cose potrebbero andare storte, quindi voglio che l'amministratore sia in grado di fermare lo script in modo pulito in qualsiasi momento.
sibaz,

11

Ho appena usato questo modello, che preferisco:

read name || name='(nobody)'

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

Imposta il valore predefinito; stampalo; leggere un nuovo valore; se c'è un nuovo valore, usalo al posto del valore predefinito. Esistono (o c'erano) alcune variazioni 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 una bash 3.xe funziona sulla maggior parte delle varianti di Unix derivate dal Sistema V, usando shell Bourne o Korn.

Si noti inoltre che l'utente probabilmente non si renderà conto di ciò che sta accadendo dietro le quinte; i loro nuovi dati verrebbero inseriti dopo il nome già visualizzato sullo schermo. Potrebbe essere meglio formattarlo:

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

printfè più portatile diecho
ghostdog74 il

3
@ ghostdog74: forse è così; quelli di noi che hanno imparato la programmazione della shell oltre 25 anni fa hanno difficoltà a capire quali delle nostre pratiche sono ancora rilevanti. Sembra sempre più che bash abbia riscritto praticamente tutto. So che printf è in circolazione da un po 'di tempo - lo uso molto raramente, anche se (probabilmente - mai?). Ho l'impressione che dovrei stare zitto su shell finché non avrò (ri) imparato la bash. È divertente; il software su cui lavoro ha script di shell che non funzionano bene, ma il problema non è bash-isms. Mi stanco solo di aggiustare ' if (test -z "$xxx"); ...' e altri shellism C.
Jonathan Leffler,

Sono sorpreso che bash supporti \c, dal momento che supporta anche echo -n! Tuttavia, è necessario aggiungere -eper ottenere l'eco di bash per interpretare le fughe. Immagino \csia per cose non echo -e "Syntax slightly off\c, but I've learned so much from what you've shared. Thanks, @JonathanLeffler!"
dette

@Jonathan Leffler Sfortunatamente, non proprio quello che l'OP ha richiesto, almeno non sulla mia versione 4.x di bash $ bash --version GNU bash, version 4.3.33(0)-release a) "Vorrei essere in grado di fornire un valore predefinito che l'utente può modificare." Il tuo echo "Please enter your name: $name \c"non mi consente di modificare il valore predefinito. b) "e il cursore si troverà dopo il valore predefinito." Nemmeno vero ... La risposta di @Paused fino a nuovo avviso. soddisfa entrambi i requisiti.
Bernie Reiter

1
#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.
Sufiyan Ghori,

-1

I parametri -e e -t non funzionano 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

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

è una soluzione per usare il parametro -e e -t. questo codice (-e e -i per il valore predefinito): leggi -e -p "Inserisci il tuo nome:" -i "Ricardo" NAME non funziona con un conto alla rovescia (-t)
speefak

Sì, ma non è stato posto nella domanda, vero?
gniourf_gniourf

3
Quello che puoi fare è fare una nuova domanda e rispondere da solo ;). Questo è consentito su SO! ma non vogliamo inquinare altre domande con cose non correlate.
gniourf_gniourf
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.