Ich habe eine Zeichenfolge mit vielen Wörtern mit mindestens einem Leerzeichen zwischen jeweils zwei. Wie kann ich die Zeichenfolge in einzelne Wörter aufteilen, um sie zu durchlaufen?
Die Zeichenfolge wird als Argument übergeben. Z.B${2} == "cat cat file"
. Wie kann ich es durchlaufen?
Wie kann ich außerdem überprüfen, ob eine Zeichenfolge Leerzeichen enthält?
Antworten:
Haben Sie versucht, die Zeichenfolgenvariable einfach an eine
for
Schleife zu übergeben? Zum einen wird Bash automatisch auf Leerzeichen aufgeteilt.quelle
A=${A}${word})
.touch NOPE; var='* a *'; for a in $var; do echo "[$a]"; done
Ausgänge[NOPE] [a] [NOPE]
anstelle der erwarteten[*] [a] [*]
(LFs werden aus Gründen der Lesbarkeit durch SPC ersetzt).Ich mag die Konvertierung in ein Array, um auf einzelne Elemente zugreifen zu können:
Jetzt können Sie direkt auf einzelne Elemente zugreifen (es beginnt mit 0):
oder konvertiere zurück in einen String, um eine Schleife zu erstellen:
Natürlich wurde das Durchlaufen der Zeichenfolge direkt zuvor beantwortet, aber diese Antwort hatte den Nachteil, dass die einzelnen Elemente für die spätere Verwendung nicht im Auge behalten wurden:
Siehe auch Bash Array-Referenz .
quelle
touch NOPE; var='* a *'; arr=($var); set | grep ^arr=
Ausgängearr=([0]="NOPE" [1]="a" [2]="NOPE")
statt der erwartetenarr=([0]="*" [1]="a" [2]="*")
Verwenden Sie einfach die eingebauten Shells "Set". Beispielsweise,
Danach werden einzelne Wörter in $ text in $ 1, $ 2, $ 3 usw. angezeigt. Aus Gründen der Robustheit wird dies normalerweise der Fall sein
um den Fall zu behandeln, in dem $ text leer ist, oder um mit einem Bindestrich zu beginnen. Beispielsweise:
Dies wird gedruckt
quelle
awk
aber esset
ist viel einfacher. Ich bin jetzt einset
Fan. Danke @Idelic!touch NOPE; var='* a *'; set -- $var; for a; do echo "[$a]"; done
Ausgaben[NOPE] [a] [NOPE]
anstelle der erwarteten[*] [a] [*]
. Verwenden Sie es nur, wenn Sie zu 101% sicher sind, dass die geteilte Zeichenfolge keine SHELL-Metazeichen enthält!set -f
davorset -- $var
undset +f
danach deaktivieren.set -f
Ihrer Lösung ist auch sicher. Istset +f
aber die Standardeinstellung jeder Shell, so ist es ein wesentliches Detail, das beachtet werden muss, da andere es wahrscheinlich nicht wissen (wie ich es auch war).Der wahrscheinlich einfachste und sicherste Weg in BASH 3 und höher ist:
(Wo
arr
ist das Array, das die geteilten Teile des Strings aufnimmt?) oder wenn die Eingabe möglicherweise Zeilenumbrüche enthält und Sie mehr als nur die erste Zeile möchten:(Bitte beachten Sie das Leerzeichen in
-d ''
, es kann nicht weggelassen werden), aber dies kann zu einem unerwarteten Zeilenumbruch führen<<<"$var"
(da dies implizit einen LF am Ende hinzufügt).Beispiel:
Gibt das erwartete aus
da diese Lösung (im Gegensatz zu allen vorherigen Lösungen hier) nicht zu unerwartetem und oft unkontrollierbarem Shell-Globbing neigt.
Auch dies gibt Ihnen die volle Leistung von IFS, wie Sie wahrscheinlich wollen:
Beispiel:
Gibt so etwas aus wie:
Wie Sie sehen, können Räume auch auf diese Weise erhalten werden:
Ausgänge
Bitte beachten Sie, dass der Umgang mit
IFS
in BASH ein eigenständiges Thema ist. Machen Sie also Ihre Tests, einige interessante Themen dazu:unset IFS
: Ignoriert Läufe von SPC, TAB, NL und startet und endet onlineIFS=''
: Keine Feldtrennung, liest einfach allesIFS=' '
: Läufe von SPC (und nur SPC)Ein letztes Beispiel
Ausgänge
während
Ausgänge
Übrigens:
Wenn Sie nicht
$'ANSI-ESCAPED-STRING'
daran gewöhnt sind, ist dies eine Zeitersparnis.Wenn Sie nicht einschließen
-r
(wie inread -a arr <<<"$var"
), wird beim Lesen ein Backslash ausgeführt. Dies bleibt als Übung für den Leser.Zur zweiten Frage:
Um auf etwas in einer Zeichenfolge zu testen, halte ich mich normalerweise daran
case
, da dies mehrere Fälle gleichzeitig prüfen kann (Hinweis: case führt nur die erste Übereinstimmung aus, wenn Sie mehrerecase
Anweisungen verwenden müssen), und dies ist häufig der Fall (Wortspiel) beabsichtigt):So können Sie den Rückgabewert so einstellen, dass nach SPC gesucht wird:
Warum
case
? Da es normalerweise etwas besser lesbar ist als Regex-Sequenzen und dank Shell-Metazeichen 99% aller Anforderungen sehr gut erfüllt.quelle
set -f
oderset -o noglob
umschalten können, sodass Shell-Metazeichen in diesem Zusammenhang keinen Schaden mehr anrichten. Aber ich bin nicht wirklich ein Freund davon, da dies viel Kraft der Shell hinterlässt / sehr fehleranfällig ist, diese Einstellung hin und her zu wechseln.;&
erreichen. Ich bin mir nicht ganz sicher, in welcher Version von Bash das aufgetaucht ist. Ich bin ein 4.3 Benutzer;&
ist das erzwungene Durchfallen ohne Musterprüfung wie in C. Und es gibt auch das,;;&
was gerade die weiteren Musterprüfungen fortsetzt. So;;
ist wieif ..; then ..; else if ..
und;;&
ist wieif ..; then ..; fi; if ..
, wo;&
ist wiem=false; if ..; then ..; m=:; fi; if $m || ..; then ..
- man hört nie auf zu lernen (von anderen););;&
bevor Sie kommentierten: D Danke, und möge die Muschel bei Ihnen sein;)Verwenden Sie grep, um nach Leerzeichen zu suchen:
quelle
echo "X" |
kann in der Regel<<<"X"
wie folgt ersetzt werden :grep -s " " <<<"This contains SPC"
. Sie können den Unterschied erkennen, wenn Sie so etwas wieecho X | read var
im Gegensatz zu tunread var <<< X
. Nur letztere importiert Variablenvar
in die aktuelle Shell, während Sie in der ersten Variante wie folgt darauf gruppieren müssen:echo X | { read var; handle "$var"; }
(A) Um einen Satz in seine Wörter aufzuteilen (durch Leerzeichen getrennt), können Sie einfach das Standard-IFS verwenden, indem Sie verwenden
Beispiel für das Ausführen des folgenden Snippets
wird ausgegeben
Wie Sie sehen, können Sie problemlos auch einfache oder doppelte Anführungszeichen verwenden.
Hinweise:
- Dies ist im Grunde die gleiche Antwort wie bei Mob , aber auf diese Weise speichern Sie das Array für weitere Anforderungen. Wenn Sie nur eine einzelne Schleife benötigen, können Sie seine Antwort verwenden, die eine Zeile kürzer ist :)
- In dieser Frage finden Sie alternative Methoden zum Teilen einer Zeichenfolge basierend auf dem Trennzeichen.
(B) Um nach einem Zeichen in einer Zeichenfolge zu suchen, können Sie auch eine Übereinstimmung mit regulären Ausdrücken verwenden.
Beispiel zum Überprüfen des Vorhandenseins eines Leerzeichens, das Sie verwenden können:
quelle
Zum Überprüfen von Leerzeichen nur mit Bash:
quelle
Dadurch wird jedes Wort ausgegeben. Sie können diese Liste nach Belieben verarbeiten.
quelle