Kann mir jemand Schritt für Schritt erklären, was in dieser Bash-Zeile passiert? Ich bin neu hier und versuche zu verstehen, wie dieser Code funktioniert, insbesondere von echo
:
read char; echo -e "YES\nNO\n" | grep -i $char
Antwort1
Die Befehle in der Zeile lesen einen String in die Variable ein char
, wahrscheinlich interaktiv vom Benutzer.
Die echo
+ grep
-Pipeline versucht zu bestimmen, ob die eingegebene Zeichenfolge eine Bejahung ist oder nicht. Dies geschieht durch Vergleichen der Wörter YES
und NO
mit der eingegebenen Zeichenfolge (mit der eingegebenen Zeichenfolge als Muster), ohne Berücksichtigung der Groß-/Kleinschreibung. Wenn der Benutzer einen Groß- oder Kleinbuchstaben oder eine Teilzeichenfolge eingibt, die im Wort enthalten ist YES
, wäre das Ergebnis YES
; wenn er einen Groß- oder Kleinbuchstaben oder eine Teilzeichenfolge eingibt, die im Wort enthalten ist NO
, wäre das Ergebnis NO
. Die Eingabe von etwas wie maybe
würde zu einer leeren Ausgabe führen.
Der Nachteil bei diesem Ansatz ist, dass, wenn der Benutzer beispielsweise eingibt, .
sowohl YES
als auch NO
übereinstimmen würden, da grep
der Punkt als regulärer Ausdruck behandelt würde, der mit jedem Zeichen übereinstimmt. Da $char
im Aufruf von nicht in Anführungszeichen steht grep
, könnte dies auch einen Denial-of-Service-Angriff auf den Computer auslösen, wenn der Benutzer ein Shell-Globbing-Muster wie /*/*/*/*/../../../../*/*/*/*
als Eingabe eingibt (Beispiel entnommen ausSicherheitsimplikationen, wenn vergessen wird, eine Variable in Bash/POSIX-Shells in Anführungszeichen zu setzen). Sie könnten mit dem Befehl auch verwirrende Ausgaben verursachen, indem Sie zB Folgendes eingeben -r -o -e . /
(würde jedes Zeichen jeder nicht-binären Datei in einer eigenen Zeile ausgeben, der der Pfadname der Datei vorangestellt ist, zu der es gehört).
Der Code, den Sie zeigen, ist "seltsam und ungewöhnlich", da er Benutzereingaben als etwas verwendet, das im WesentlichenCode, d. h. es verwendet die Benutzereingaben alsMusterund testet statischDatengegen dieses variable Muster. Dies ist das Gegenteil von dem, was man normalerweise tut, nämlich die Eingabe des Benutzers zu nehmen und diese variablen Daten gegen ein statisches Muster zu testen.
Üblicher ist die Verwendung von Code wie dem folgenden:
read -p 'Yes/[N]o: ' yesno
if [[ $yesno == [Yy]* ]]; then
# code for affirmative
else
# code for non-affirmative
fi
Der obige Code liest eine Zeichenfolge vom Benutzer und prüft, ob sie mit einem y
oder einem Y
Zeichen beginnt. Wenn dies der Fall ist, wird der erste Zweig der if
Anweisung genommen, andernfalls wird standardmäßig der else
Zweig genommen.
Sie können natürlich auch das ganze Wort testen YES
, [Yy][Ee][Ss]
auf eine Übereinstimmung ohne Berücksichtigung der Groß-/Kleinschreibung prüfen oder eine richtige Eingabeschleife mit Überprüfung ausführen:
while true; do
read -p 'Yes/No: ' yesno
if [ "$yesno" = Yes ] || [ "$yesno" = No ]; then
break
fi
echo 'Please enter "Yes" or "No"' >&2
done
# $yesno is either Yes or No here
(oder etwas ähnliches).
Beachten Sie, dass die beiden Beispielcodes oben die Benutzereingaben ausschließlich als Daten und nie als Muster verwenden.
Wenn Sie Ihren ursprünglichen Befehl minimal in etwas Idiomatischeres (aber funktional anderes und wahrscheinlich nicht narrensicheres) umschreiben, wird daraus
read yesno; printf '%s\n' "${yesno^^}" | grep -i -w -E 'yes|no'
Dies würde Großbuchstaben YES
oder zurückgeben NO
, wenn der Benutzer yes
oder eingegeben hat. Dies ist funktional anders, da der Benutzer beispielsweise no
mehr eingeben muss als nur e
für ein .yes
Antwort2
Sehen wir uns nun die einzelnen Befehle der Reihe nach an:
read char
Dies liest von der Standardeingabe (normalerweise von Ihrer Tastatur, kann aber auch eine indirekte Datei oder ein weitergeleiteter Stream sein, siehe unten) und fügt die empfangenen Daten in eine Variable mit dem Namen ein char
.
echo -e "YES\nNO\n"
echo
zeigt die angegebenen Parameter auf der Standardausgabe (normalerweise dem Terminal) an. Der -e
Schalter ermöglicht (oft, aber nicht immer; echo
ist etwas problematisch im Hinblick auf eine konsistente Implementierung) das e
Blockieren bestimmter Zeichen, um eine rudimentäre Formatierung vorzunehmen. In diesem Fall wird verwendet \n
, was ein maskiertes ist n
, was eine Abkürzung für eine n
Ewline ist.
grep -i $char
grep
ist ein Tool zum Durchsuchen bereitgestellter Eingaben, um zu sehen, ob es Übereinstimmungen für das bereitgestellte Muster gibt. Der -i
Schalter gibt an, dass es sich um eine i
Suche ohne Berücksichtigung der Groß- und Kleinschreibung handelt.
Zwischen |
den Befehlen echo
und grep
steht eine „Pipe“. Diese verbindet die Ausgabe des ersten Befehls mit der Eingabe des zweiten, was bedeutet, dass grep
dieser Korpus nach dem Muster durchsucht wird, das sich im Inhalt der Variable widerspiegelt char
:
YES
NO
Das praktische Ergebnis dieser Befehlsfolge besteht darin, sich die bereitgestellte Eingabe anzusehen (angenommen wird aufgrund des Variablennamens, dass es sich um ein einzelnes Zeichen handelt, dies wird jedoch nicht überprüft). Wenn dieses Zeichen ein Y
, E
, S
, y
, e
, oder s
ist, lautet die Ausgabe YES
. Wenn dieses Zeichen ein N
, O
, n
, oder o
ist, lautet die Ausgabe NO
. Wenn die Eingabe jedoch (beispielsweise) yo
oder ist ne
, wird nichts ausgegeben.
Wie bereits erwähnt, wird die Annahme, dass die Eingabe aus einem Zeichen besteht, nicht überprüft. Dies ist nicht das einzige Antimuster in der angegebenen Beispielbefehlssequenz. Beispielsweise werden Variablen nicht in Anführungszeichen gesetzt; und es grep
wird ein reguläres Ausdruckstool ( ) verwendet, ohne dass die Eingabe auf Regex-Platzhalter überprüft wird.
Antwort3
Ein "Zeichen" (eher: String) wird aus eingelesen /dev/stdin
. Das heißt: Du tippst es ein.
Anschließend werden zwei Zeilen an , also Ihre Konsole, ausgegeben /dev/stdout
.
Und über die Pipe (das „|“) wird dann nach der Case-Insensitive-Version Ihrer Eingabe gesucht.
Das heißt, wenn Sie „bar“ eingeben, wird der Vorgang einfach beendet, ohne dass eine Ausgabe erfolgt. Wenn Sie jedoch beispielsweise „y“ eingeben, wird die Zeile „YES“ ausgegeben, wobei das „Y“ höchstwahrscheinlich sogar hervorgehoben wird.