Ich möchte, dass der Benutzer mit einer Frage aufgefordert wird und dann die Antwort bereitstellt, die unter einer Variablen namens i gespeichert wird. Wenn dann die Antwort (welche) ist eine Datei) existiert und ist beschreibbar, sie liest sie und erfasst Dinge in der Datei und schreibt diese Dinge in eine neue. Wenn die Datei nicht vorhanden ist oder der Benutzer nicht über ausreichende Berechtigungen für diese Datei verfügt, wird eine Warnung angezeigt, das Programm wird 3 Sekunden lang in den Ruhezustand versetzt und die Schleifen werden erneut gestartet. Warum funktioniert es nicht? Die Warnung wird einfach nicht verschwinden und die Schleife wird auch nicht weiterlaufen.
echo "$(tput setaf 4) Tell me where the file is:" printf "\n" a=false while [ $a=true ]; do read i if [ -w $i ] then cat $i | grep stuff > i2 else a=true printf "Oh something is wrong, try again!" sleep 3 fi done
Antwort
Sie haben Syntax- und logische Fehler.
Die $a=true
ist nur eine Zeichenfolge, keine Vergleichsoperation. Durch Leerzeichen trennen, damit der Vergleich stattfindet: "$a" = true
.
Wenn dies funktioniert, wird die Schleife überhaupt nicht eingegeben, wenn Sie a=false
im Voraus.
SOLLTEN Sie endlich in die Schleife geraten, können Sie nicht beenden, da a
niemals ist auf etwas anderes als true
gesetzt, noch wird ein anderer Exit-Mechanismus (z. B. break
) bereitgestellt.
Antwort
Wie andere bereits betont haben, enthält Ihr Code logische Fehler und Syntaxfehler. Die ShellCheck-Site ist gut geeignet, um Syntaxfehler auszusortieren.
Hier ist meine Meinung dazu. Ich habe zwei Versionen des Codes Der erste (den ich bevorzuge) hat keine Benutzerinteraktion, sondern verwendet einen Pfadnamen in der Befehlszeile. Der zweite fragt interaktiv nach einem Pfadnamen.
Der Grund, warum der erste nicht interaktiv nach einem fragt Pfadname ist, dass es kaum einen Unterschied macht, ob der Benutzer des Skripts den Pfadnamen in die Befehlszeile oder an die Eingabeaufforderung Ihres Skripts schreibt, und wenn die Skriptaufforderung für den Pfadnamen von der Verwendung von z ein Cron-Job oder irgendwo anders, wo möglicherweise kein Terminal angeschlossen ist.
#!/bin/sh pathname=$1 if ! grep "pattern" <$pathname >i2; then echo "Something is wrong" >&2 fi
Die echo
oben ist Wird ausgeführt, wenn
- die Datei in
$pathname
„nicht gelesen werden kann oder - die Datei
i2
kann nicht beschrieben werden oder - das Muster wurde nicht in
$pathname
gefunden (dies unterscheidet sich von Ihrem Code, aber siehe unten) .
Die Fehlermeldung wird in den Standardfehler geschrieben, wie es bei Diagnosemeldungen im Allgemeinen üblich ist.
Mit interaktiver Aufforderung und Verzögerung:
#!/bin/bash while true; do read -r -p "Pathname: " pathname if grep "pattern" <$pathname >i2; then break fi echo "Something is wrong" >&2 sleep 3 done
Hier haben wir eine Endlosschleife, die vom Benutzer liest und aus der Schleife ausbricht, wenn der Aufruf grep
in Ordnung war. Wenn grep
aus irgendeinem Grund fehlgeschlagen ist (einer der drei oben genannten Gründe), wird der Pfadname erneut abgefragt.
Beide Codeteile mit einem separaten Test auf eine lesbare Datei (die grep
kann fehlschlagen, indem nichts gefunden wird oder nicht in die Ausgabedatei geschrieben werden kann.
Zuerst die nicht interaktive version:
#!/bin/sh pathname=$1 if [ ! -r "$pathname" ]; then echo "Something is wrong" >&2 fi grep "pattern" <$pathname >i2
Dann die interaktive Version:
#!/bin/bash while true; do read -r -p "Pathname: " pathname if [ -r "$pathname" ]; then grep "pattern" <$pathname >i2 break fi echo "Something is wrong" >&2 sleep 3 done
Oder eine interaktive Version Dabei behandelt die Schleife nur Benutzereingaben und -überprüfungen:
#!/bin/bash while true; do read -r -p "Pathname: " pathname [ -r "$pathname" ] && break echo "Something is wrong" >&2 sleep 3 done grep "pattern" <$pathname >i2
Antwort
Verwenden Sie einfach break, um die Endlosschleife wie folgt zu stoppen:
echo "$(tput setaf 4) Tell me where the file is:" echo # This prints empty line like printf "\n" while true; do # "while true" or "while :" is infinite loop read i if [ -r $i ] # You probably mean -r (readable) and not -w (writable) then cat $i | grep stuff > i2 break # "break" ends loop else echo -n "Oh something is wrong, try again!" # "echo -n" means print without newline character sleep 3 fi done
Geänderte Stellen haben Kommentare mit Beschreibung.
Kommentare
-
grep <$i >i2
anstelle voncat
. Geben Sie bei Bedarf auch Variablenerweiterungen an, wie im Test .