Grundlegendes zu den Befehlen read, echo und grep in einer Bash-Befehlszeile

Grundlegendes zu den Befehlen read, echo und grep in einer Bash-Befehlszeile

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 YESund NOmit 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 maybewürde zu einer leeren Ausgabe führen.

Der Nachteil bei diesem Ansatz ist, dass, wenn der Benutzer beispielsweise eingibt, .sowohl YESals auch NOübereinstimmen würden, da grepder Punkt als regulärer Ausdruck behandelt würde, der mit jedem Zeichen übereinstimmt. Da $charim 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 yoder einem YZeichen beginnt. Wenn dies der Fall ist, wird der erste Zweig der ifAnweisung genommen, andernfalls wird standardmäßig der elseZweig 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 YESoder zurückgeben NO, wenn der Benutzer yesoder eingegeben hat. Dies ist funktional anders, da der Benutzer beispielsweise nomehr eingeben muss als nur efü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"

echozeigt die angegebenen Parameter auf der Standardausgabe (normalerweise dem Terminal) an. Der -eSchalter ermöglicht (oft, aber nicht immer; echoist etwas problematisch im Hinblick auf eine konsistente Implementierung) das eBlockieren 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 nEwline ist.

grep -i $char

grepist ein Tool zum Durchsuchen bereitgestellter Eingaben, um zu sehen, ob es Übereinstimmungen für das bereitgestellte Muster gibt. Der -iSchalter gibt an, dass es sich um eine iSuche ohne Berücksichtigung der Groß- und Kleinschreibung handelt.

Zwischen |den Befehlen echound grepsteht eine „Pipe“. Diese verbindet die Ausgabe des ersten Befehls mit der Eingabe des zweiten, was bedeutet, dass grepdieser 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 sist, lautet die Ausgabe YES. Wenn dieses Zeichen ein N, O, n, oder oist, lautet die Ausgabe NO. Wenn die Eingabe jedoch (beispielsweise) yooder 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 grepwird 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.

verwandte Informationen