Ich habe eine Zeichenfolge in Bash:
string="My string"
Wie kann ich testen, ob es eine andere Zeichenfolge enthält?
if [ $string ?? 'foo' ]; then
echo "It's there!"
fi
Wo ??
ist mein unbekannter Betreiber? Benutze ich echo und grep
?
if echo "$string" | grep 'foo'; then
echo "It's there!"
fi
Das sieht etwas ungeschickt aus.
expr
Befehl hier verwendenAntworten:
Sie können die Antwort von Marcus (* Platzhalter) auch außerhalb einer case-Anweisung verwenden, wenn Sie doppelte Klammern verwenden:
Beachten Sie, dass Leerzeichen in der Nadelkette zwischen doppelten Anführungszeichen stehen müssen und die
*
Platzhalter außerhalb liegen sollten. Beachten Sie auch, dass ein einfacher Vergleichsoperator verwendet wird (dh==
), nicht der Regex-Operator=~
.quelle
#!/bin/sh
. Versuchen Sie es#!/bin/bash
stattdessen.[[
. Siehe ideone.com/ZSy1gZWenn Sie den Regex-Ansatz bevorzugen:
quelle
=~
Operator durchsucht bereits die gesamte Zeichenfolge nach einer Übereinstimmung. die.*
hier sind irrelevant. Außerdem sind Anführungszeichen Backslashes im Allgemeinen vorzuziehen:[[ $string =~ "My s" ]]
E14)
. Es ist wahrscheinlich am besten, einer Variablen zuzuweisen (in Anführungszeichen) und dann zu vergleichen. So:re="My s"; if [[ $string =~ $re ]]
if [[ ! "abc" =~ "d" ]]
ist wahr.number=2; if [[ "1, 2, 4, 5" = *${number}* ]]; then echo forward $number; fi; if [[ *${number}* = "1, 2, 4, 5" ]]; then echo backwards $number; fi;
Ich bin mir nicht sicher, ob ich eine if-Anweisung verwenden soll, aber Sie können mit einer case-Anweisung einen ähnlichen Effekt erzielen:
quelle
[[ $string == *foo* ]]
funktioniert auch in einigen POSIX-kompatiblen sh-Versionen (z. B./usr/xpg4/bin/sh
unter Solaris 10) und ksh (> = 88)[[
... der Gehäuseschalter hat funktioniert!stringContain
Varianten (kompatibel oder fallunabhängig)Da diese Stack Overflow-Antworten hauptsächlich über Bash berichten , habe ich ganz unten in diesem Beitrag eine fallunabhängige Bash-Funktion veröffentlicht ...
Wie auch immer, da ist meine
Kompatible Antwort
Da es bereits viele Antworten gibt, die Bash-spezifische Funktionen verwenden, gibt es eine Möglichkeit, unter Shells mit schlechteren Funktionen wie BusyBox zu arbeiten :
In der Praxis könnte dies Folgendes ergeben:
Dies wurde unter Bash, Dash , KornShell (
ksh
) und ash (BusyBox) getestet und das Ergebnis ist immer:In eine Funktion
Wie von @EeroAaltonen gefragt, ist hier eine Version derselben Demo, die unter denselben Shells getestet wurde:
Dann:
Hinweis: Sie müssen Anführungszeichen und / oder doppelte Anführungszeichen maskieren oder doppelt einschließen:
Einfache Funktion
Dies wurde unter BusyBox, Dash und natürlich Bash getestet:
Dann jetzt:
... Oder wenn die übermittelte Zeichenfolge leer sein könnte, wie von @Sjlver hervorgehoben, würde die Funktion wie folgt lauten:
oder wie in Adrian Günters Kommentar vorgeschlagen , um
-o
Schalter zu vermeiden :Letzte (einfache) Funktion:
Und die Tests umkehren, um sie möglicherweise schneller zu machen:
Mit leeren Zeichenfolgen:
Groß- und Kleinschreibung unabhängig (nur Bash!)
Um Zeichenfolgen ohne Berücksichtigung der Groß- und Kleinschreibung zu testen, konvertieren Sie einfach jede Zeichenfolge in Kleinbuchstaben:
Prüfen:
quelle
string_contains() { [ -z "${2##*$1*}" ] && [ -n "$2" -o -z "$1" ]; }
Ein letzter Gedanke: Enthält die leere Zeichenfolge die leere Zeichenfolge? Die obige Version ja (wegen des-o -z "$1"
Teils).Sie sollten sich daran erinnern, dass Shell-Skripte weniger eine Sprache als eine Sammlung von Befehlen sind. Instinktiv denken Sie, dass diese "Sprache" erfordert, dass Sie einem
if
mit einem[
oder einem folgen[[
. Beides sind nur Befehle, die einen Exit-Status zurückgeben, der Erfolg oder Misserfolg anzeigt (genau wie jeder andere Befehl). Aus diesem Grund würde ich verwendengrep
und nicht den[
Befehl.Mach einfach:
Nachdem Sie nun
if
den Exit-Status des darauf folgenden Befehls (einschließlich Semikolon) testen möchten, sollten Sie die Quelle der zu testenden Zeichenfolge erneut überprüfen.Die
-q
Option bewirkt, dass grep nichts ausgibt, da wir nur den Rückkehrcode wollen.<<<
Lässt die Shell das nächste Wort erweitern und es als Eingabe für den Befehl verwenden, eine einzeilige Version des<<
hier gezeigten Dokuments (ich bin nicht sicher, ob dies Standard oder ein Bashismus ist).quelle
if grep -q foo <(echo somefoothing); then
echo
portierbar ist. Wenn Sie eine Variable übergeben, verwenden Sieprintf '%s' "$string
stattdessen.grep -q foo <<<"$mystring"
hoch : implizieren 1 Gabel und ist Bashism undecho $mystring | grep -q foo
implie 2 Gabeln (eine für das Rohr und die zweite für das Laufen/path/to/grep
)echo
ohne Flags kann immer noch unerwartete Portabilitätsprobleme haben, wenn die Argumentzeichenfolge Backslash-Sequenzen enthält.echo "nope\c"
wird erwartet, dass auf einigen Plattformen wieecho -e "nope"
auf anderen funktioniert .printf '%s' "nope"
vsprintf '%s\n' 'nope\c'
Die akzeptierte Antwort ist am besten, aber da es mehr als einen Weg gibt, ist hier eine andere Lösung:
${var/search/replace}
wird$var
mit der ersten Instanz vonsearch
ersetzt durchreplace
, wenn es gefunden wird (es ändert sich nicht$var
). Wenn Sie versuchen,foo
durch nichts zu ersetzen , und sich die Zeichenfolge geändert hat, wurde offensichtlichfoo
gefunden.quelle
Es gibt also viele nützliche Lösungen für die Frage - aber welche ist am schnellsten / verbraucht die wenigsten Ressourcen?
Wiederholte Tests mit diesem Rahmen:
TEST jedes Mal ersetzen:
(doContain war in der Antwort von F. Houri)
Und zum Kichern:
Die einfache Substitutionsoption gewinnt also vorhersehbar, ob in einem erweiterten Test oder in einem Fall. Der Fall ist tragbar.
Das Auspfeifen auf 100000 Greps ist vorhersehbar schmerzhaft! Die alte Regel über die Verwendung externer Dienstprogramme ohne Notwendigkeit gilt.
quelle
[[ $b == *$a* ]]
.case
gewinnt mit dem geringsten Gesamtzeitverbrauch. Sie vermissen jedoch ein Sternchen danach$b in *$a
. Ich bekomme etwas schnellere Ergebnisse[[ $b == *$a* ]]
alscase
mit dem korrigierten Fehler, aber es könnte natürlich auch von anderen Faktoren abhängen.[[ $b == *$a* ]]
ist schnell undcase
fast genauso schnell (und angenehm POSIX-kompatibel).Dies funktioniert auch:
Und der negative Test ist:
Ich nehme an, dieser Stil ist etwas klassischer - weniger abhängig von den Merkmalen der Bash-Shell.
Das
--
Argument ist reine POSIX-Paranoia, die zum Schutz vor Eingabezeichenfolgen verwendet wird, die Optionen wie--abc
oder ähneln-a
.Hinweis: In einer engen Schleife ist dieser Code viel langsamer als die Verwendung interner Bash-Shell-Funktionen, da ein (oder zwei) separate Prozesse erstellt und über Pipes verbunden werden.
quelle
echo
ist nicht portierbar, sollten Sieprintf '%s' "$haystack
stattdessen verwenden.echo
alles andere als wörtlichen Text ohne Escapezeichen, der nicht mit a beginnt-
. Es mag für Sie funktionieren, ist aber nicht portabel. Sogar Bashsecho
verhalten sich unterschiedlich, je nachdem, ob diexpg_echo
Option aktiviert ist. PS: Ich habe vergessen, das doppelte Anführungszeichen in meinem vorherigen Kommentar zu schließen.--
ist nicht in der POSIX-Spezifikation für aufgeführtprintf
, aber Sie sollten esprintf '%s' "$anything"
trotzdem verwenden, um Probleme zu vermeiden, wenn es$anything
ein%
Zeichen enthält .Bash 4+ Beispiele. Hinweis: Wenn Sie keine Anführungszeichen verwenden, treten Probleme auf, wenn Wörter Leerzeichen usw. enthalten. Zitieren Sie immer in Bash, IMO.
Hier sind einige Beispiele für Bash 4+:
Beispiel 1: Überprüfen Sie die Zeichenfolge auf "Ja" (Groß- und Kleinschreibung wird nicht berücksichtigt):
Beispiel 2: Überprüfen Sie die Zeichenfolge auf "Ja" (Groß- und Kleinschreibung wird nicht berücksichtigt):
Beispiel 3: Überprüfen Sie die Zeichenfolge auf "Ja" (Groß- und Kleinschreibung beachten):
Beispiel 4: Überprüfen Sie die Zeichenfolge auf "Ja" (Groß- und Kleinschreibung beachten):
Beispiel 5, genaue Übereinstimmung (Groß- und Kleinschreibung beachten):
Beispiel 6, genaue Übereinstimmung (ohne Berücksichtigung der Groß- und Kleinschreibung):
Beispiel 7, genaue Übereinstimmung:
Beispiel 8, Platzhalterübereinstimmung .ext (Groß- und Kleinschreibung wird nicht berücksichtigt):
Genießen.
quelle
Wie wäre es damit:
quelle
Wie Paulus erwähnte in seinem Leistungsvergleich :
Dies ist POSIX-konform wie der 'case "$ string" in' der Antwort von Marcus , aber es ist etwas einfacher zu lesen als die Antwort auf die case-Anweisung. Beachten Sie auch, dass dies viel langsamer ist als die Verwendung einer case-Anweisung. Wie Paul betonte, verwenden Sie es nicht in einer Schleife.
quelle
Diese Stapelüberlauf-Antwort war die einzige, die Leerzeichen abfing und Zeichen strich:
quelle
quelle
echo "Couldn't find
Anweisung am Ende ein guter Trick ist, um 0 Exit-Status für diese übereinstimmenden Befehle zurückzugeben.|| echo "Couldn't find"
Sie einen Fehler-Exit-Status zurück, wenn keine Übereinstimmung vorliegt. Dies möchten Sie möglicherweise nicht, wenn Sie beispielsweise eine CI-Pipeline ausführen, in der alle Befehle zurückgegeben werden sollen Nicht-Fehler-Exit-StatusEines ist:
quelle
expr
ist eines dieser Dienstprogramme für Schweizer Taschenmesser, die normalerweise alles tun können, was Sie tun müssen, sobald Sie herausgefunden haben, wie es geht, aber wenn es einmal implementiert ist, können Sie sich nie mehr daran erinnern, warum oder wie es das tut, was es tut, also Sie Berühren Sie es nie wieder und hoffen Sie, dass es nie aufhört zu tun, was es tut.expr
in seltenen Fällen, wenn die Portabilität die Verwendung von Bash (z. B. inkonsistentes Verhalten in älteren Versionen), tr (überall inkonsistent) oder sed (manchmal zu langsam) verhindert. Aber aus persönlicher Erfahrung mussexpr
ich , wenn ich diese -ismen noch einmal lese , zur Manpage zurückkehren. Also, ich würde nur kommentieren, dass jede Verwendung vonexpr
kommentiert werden ...expr
undtest
implementiert, um sie auszuführen. In der heutigen Zeit gibt es normalerweise bessere Werkzeuge, von denen viele in jede moderne Hülle eingebaut sind. Ich denke, estest
hängt immer noch drin, aber niemand scheint zu fehlenexpr
.Ich mag sed.
Bearbeiten, Logik:
Verwenden Sie sed, um die Instanz des Teilstrings aus dem String zu entfernen
Wenn sich die neue Zeichenfolge von der alten unterscheidet, ist eine Teilzeichenfolge vorhanden
quelle
grep -q
ist für diesen Zweck nützlich.Das gleiche mit
awk
:Ausgabe:
Ausgabe:
Ursprüngliche Quelle: http://unstableme.blogspot.com/2008/06/bash-search-letter-in-string-awk.html
quelle
echo
ist nicht portierbar, sollten Sieprintf '%s' "$string"
stattdessen verwenden. Ich bearbeite die Antwort, weil der Benutzer nicht mehr zu existieren scheint.echo
@ nyuszika7h nicht portabel?Ich habe festgestellt, dass ich diese Funktionalität ziemlich häufig benötige, daher verwende ich eine hausgemachte Shell-Funktion
.bashrc
wie diese, mit der ich sie so oft wie nötig wiederverwenden kann, mit einem leicht zu merkenden Namen:Um zu testen, ob
$string1
(z. B. abc ) in$string2
(z. B. 123abcABC ) enthalten ist , muss ich beispielsweise nur ausführenstringinstring "$string1" "$string2"
und nach dem Rückgabewert suchenquelle
x
Hack nur für sehr alte Muscheln erforderlich ist .Meine .bash_profile- Datei und wie ich grep verwendet habe:
Wenn die Umgebungsvariable PATH meine beiden
bin
Verzeichnisse enthält, hängen Sie sie nicht an.quelle
grep -q -E 'pattern1|...|patternN'
.Erweiterung der hier beantworteten Frage Wie können Sie feststellen, ob eine Zeichenfolge eine andere Zeichenfolge in POSIX sh enthält? ::
Diese Lösung funktioniert mit Sonderzeichen:
quelle
contains "-n" "n"
funktioniert hier nicht, daecho -n
der-n
als Option geschluckt wird! Eine beliebte Lösung dafür ist die Verwendungprintf "%s\n" "$string"
.Da die POSIX / BusyBox-Frage geschlossen ist, ohne die richtige Antwort zu geben (IMHO), werde ich hier eine Antwort veröffentlichen.
Die kürzest mögliche Antwort lautet:
oder
Beachten Sie, dass der doppelte Hash bei einigen Shells obligatorisch ist (
ash
). Oben wird ausgewertet,[ stringvalue ]
wenn der Teilstring nicht gefunden wird. Es wird kein Fehler zurückgegeben. Wenn der Teilstring gefunden wird, ist das Ergebnis leer und wird ausgewertet[ ]
. Dies löst den Fehlercode 1 aus, da die Zeichenfolge vollständig ersetzt wird (aufgrund von*
) .Die kürzeste häufigere Syntax:
oder
Noch einer:
oder
Beachten Sie das einzelne Gleichheitszeichen!
quelle
Genaue Wortübereinstimmung:
quelle
Versuchen Sie es mit Oobash.
Es ist eine String-Bibliothek im OO-Stil für Bash 4. Sie unterstützt deutsche Umlaute. Es ist in Bash geschrieben.
Viele Funktionen stehen zur Verfügung:
-base64Decode
,-base64Encode
,-capitalize
,-center
,-charAt
,-concat
,-contains
,-count
,-endsWith
,-equals
,-equalsIgnoreCase
,-reverse
,-hashCode
,-indexOf
,-isAlnum
,-isAlpha
,-isAscii
,-isDigit
,-isEmpty
,-isHexDigit
,-isLowerCase
,-isSpace
,-isPrintable
,-isUpperCase
,-isVisible
,-lastIndexOf
,-length
,-matches
,-replaceAll
,-replaceFirst
,-startsWith
,-substring
,-swapCase
,-toLowerCase
,-toString
,-toUpperCase
,-trim
, und-zfill
.Schauen Sie sich das enthält Beispiel:
oobash ist auf Sourceforge.net verfügbar .
quelle
Ich benutze diese Funktion (eine Abhängigkeit nicht enthalten, aber offensichtlich). Es besteht die unten gezeigten Tests. Wenn die Funktion einen Wert> 0 zurückgibt, wurde die Zeichenfolge gefunden. Sie können stattdessen genauso gut 1 oder 0 zurückgeben.
quelle
Dies ist die gleiche Antwort wie https://stackoverflow.com/a/229585/11267590 . Aber einfacher Stil und auch POSIX-konform.
quelle
Dies wird jedes Auftreten von a oder b oder c finden
quelle
Das generische Nadelheuhaufen- Beispiel folgt mit Variablen
quelle