Lesen Sie eine Variable in Bash mit einem Standardwert


191

Ich muss einen Wert vom Terminal in einem Bash-Skript lesen. Ich möchte in der Lage sein, einen Standardwert anzugeben, den der Benutzer ändern kann.

# Please enter your name: Ricardo^

In diesem Skript lautet die Eingabeaufforderung "Bitte geben Sie Ihren Namen ein:". Der Standardwert ist "Ricardo" und der Cursor befindet sich hinter dem Standardwert. Gibt es eine Möglichkeit, dies in einem Bash-Skript zu tun?

Antworten:


278

Sie können die Parametererweiterung verwenden, z

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

Das Einfügen des Standardwerts in die Eingabeaufforderung in Klammern ist eine weit verbreitete Konvention


7
Am Ende habe ich etwas getan, das darauf basiert. In eine temporäre Variable einlesen inputund dann verwenden name=${input:-$name}.
Ricardo Marimon

41
Dies beantwortet die Frage nicht wirklich. Der Standardwert sollte in der Eingabeaufforderung angezeigt werden.
Dr. Person Person II

3
und was wird name=${!input:-$name}tun?
Harry Lee

8
@ Dr.PersonPersonII - Sie können den Standardwert wie folgt hinzufügen: read -p "Geben Sie den Namen des Remote-Hosts ein [$ remote_host_default]:" remote_host remote_host = $ {remote_host: - $ remote_host_default}
Dobler

4
$1wird${1:-some_default_string}
ThorSummoner

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

echo $NAME

1
Gute Antwort! Ich möchte nur erwähnen, dass ich Probleme damit hatte, weil ich den Raum zwischen "Ricardo" und NAME nicht gesehen habe, aber als ich das herausgefunden habe ... Magie ! Danke dir!
Herr Mikkél

40
Leider ist -i keine gültige Option für OSX 10.7
undefiniert

3
@BrianMortenson Sie können Bash mit Homebrew aktualisieren
antonagestam

2
Diese Antwort zeigt, wie dies unter OS X (Bash 3.x) funktioniert
Christoph Petschnig

3
Beachten Sie nur, dass -edies obligatorisch zu sein scheint, um -itatsächlich arbeiten zu können
MestreLion

48

In Bash 4:

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

Dies zeigt den Namen nach der Eingabeaufforderung wie folgt an:

Please enter your name: Ricardo

mit dem Cursor am Ende des Namens und ermöglicht dem Benutzer, ihn zu bearbeiten. Die letzte Zeile ist optional und erzwingt, dass der Name der ursprüngliche Standardwert ist, wenn der Benutzer die Eingabe oder den Standardwert löscht (Übermittlung einer Null).


Bash4 kann nicht verwendet werden, da es in Debian-Distributionen nicht Standard ist. Ich brauche etwas, das ohne großen Aufwand funktioniert.
Ricardo Marimon

1
keine Notwendigkeit für die letzte Zeile des Codes, verwenden Sie einfach namestatt inputim readBefehl.
RNA

1
@RNAer: Durch Verwendung der zusätzlichen Variablen $namebleibt der Wert von erhalten, wenn der Benutzer den vorgeschlagenen Wert löscht (und somit eine Nullzeichenfolge eingibt). Es hängt alles davon ab, was Sie brauchen. Das habe ich in meiner Antwort gesagt. Sie haben jedoch Recht, dass ich expliziter hätte sein können und gesagt habe, dass die Variable hätte sein können, wenn die optionale Zeile nicht verwendet worden wäre name.
Bis auf weiteres angehalten.

1
@ TennisWilliamson: Du hast recht. Es ist eine gute Praxis, wenn man das will.
RNA

16

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"

Probelauf:

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

Ich mag das, weil es der Konvention folgt, die ich in vielen Shell-Skripten sehe, bei denen der Standardwert in eckigen Klammern vor dem Doppelpunkt steht. Vielen Dank!!!
Morphatic

16

Ich fand diese Frage und suchte nach einer Möglichkeit, etwas zu präsentieren wie:

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

Anhand der obigen Beispiele folgerte ich Folgendes: -

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

Ich hoffe, das hilft jemandem, nicht über die Logik nachdenken zu müssen, wenn er auf dasselbe Problem stößt


Sehr schön. Es könnte sogar ein wenig verbessert werden, die Frage zu wiederholen, wenn jemand nur "k" oder etwas anderes als die angegebenen Auswahlmöglichkeiten eingibt.
Erikbwork

1
Ich habe diesen Kommentar gerade nach einem zerkratzten Juckreiz geschrieben. Ich habe jetzt eine Shell-Funktion, die die oben genannten enthält, und ich neige dazu, diese zu verwenden. Shell scheint nicht gut zu schleifen, also versuche ich es zu vermeiden. Ich könnte das Ergebnis meiner Funktion testen und es noch einmal versuchen, aber im Grunde schreibe ich Admin-Tools, bei denen möglicherweise Probleme auftreten. Daher möchte ich, dass der Admin das Skript jederzeit sauber stoppen kann.
Sibaz

11

Ich habe gerade dieses Muster verwendet, das ich bevorzuge:

read name || name='(nobody)'

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

Legen Sie die Standardeinstellung fest. Druck es; einen neuen Wert lesen; Wenn es einen neuen Wert gibt, verwenden Sie ihn anstelle des Standardwerts. Es gibt (oder gab) einige Unterschiede zwischen Shells und Systemen, wie eine neue Zeile am Ende einer Eingabeaufforderung unterdrückt werden kann. Die '\ c'-Notation scheint unter MacOS X 10.6.3 mit einem 3.x-Bash zu funktionieren und funktioniert mit den meisten von System V abgeleiteten Unix-Varianten unter Verwendung von Bourne- oder Korn-Shells.

Beachten Sie auch, dass der Benutzer wahrscheinlich nicht erkennen würde, was sich hinter den Kulissen abspielt. Ihre neuen Daten werden nach dem Namen eingegeben, der bereits auf dem Bildschirm angezeigt wird. Es könnte besser sein, es zu formatieren:

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

printfist tragbarer alsecho
ghostdog74

3
@ Ghostdog74: vielleicht so; Diejenigen von uns, die vor über 25 Jahren Shell-Programmierung gelernt haben, haben es schwer herauszufinden, welche unserer Praktiken noch relevant sind. Es sieht zunehmend so aus, als hätte bash so ziemlich alles neu geschrieben. Ich weiß, dass printf schon eine Weile als Befehl verwendet wurde - ich benutze es jedoch sehr selten (wahrscheinlich - nie?). Ich habe den Eindruck, ich sollte die Klappe halten, bis ich Bash (wieder) gelernt habe. Es ist lustig; Die Software, an der ich arbeite, enthält Shell-Skripte, die nicht gut funktionieren - aber das Problem sind keine Bash-Ismen. Ich habe es einfach satt, ' if (test -z "$xxx"); ...' und andere C-Shellismen zu reparieren.
Jonathan Leffler

Ich bin erstaunt, dass Bash unterstützt \c, da es auch unterstützt echo -n! Sie müssen jedoch hinzufügen -e, um das Bash-Echo für die Interpretation von Escape-Zeichen zu erhalten. Ich denke, \cist für Dinge, die nicht gesagt werden:echo -e "Syntax slightly off\c, but I've learned so much from what you've shared. Thanks, @JonathanLeffler!"
jpaugh

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
Bitte fügen Sie Ihrer Antwort eine Erklärung hinzu.
Sufiyan Ghori

-1

Die Parameter -e und -t funktionieren nicht zusammen. Ich habe einige Ausdrücke ausprobiert und das Ergebnis war das folgende Code-Snippet:

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

Ihre Antwort hat nicht viel mit der Frage zu tun, oder?…
gniourf_gniourf

Es ist eine Problemumgehung für die Verwendung der Parameter -e und -t. Diese Codeline (-e und -i als Standardwert): read -e -p "Geben Sie Ihren Namen ein:" -i "Ricardo" NAME funktioniert nicht mit einem Countdowntimer (-t)
speefak

Ja, aber das wird in der Frage nicht gestellt, oder?
gniourf_gniourf

3
Sie können eine neue Frage stellen und diese selbst beantworten ;). Dies ist auf SO erlaubt! aber wir wollen andere Fragen nicht mit nicht verwandten Dingen verschmutzen.
gniourf_gniourf
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.