Relativ häufig braucht man im Programmieralltag die Überprüfung, ob sich ein bestimmter Teilstring in einem größeren String befindet. Diese Funktion kommt zum Beispiel zum Einsatz, wenn man prüfen möchte, ob ein String unzulässige Zeichen enthält (bspw ein Komma, wenn man dieses später als Mod-Rewrite-Trennzeichen für die URL-Parameter verwenden möchte).
Folgende 3 Möglichkeiten werden hinsichtlich ihrer Performance untersucht:
$string = "Dies ist ein String, der keine große Aufgabe hat"; if($string!=str_replace("String","",$string)) echo "String ist enthalten"; if(strpos($string,"String")!==false) echo "String ist enthalten"; if(preg_match("/String/",$string)) echo "String ist enthalten"; |
Die erste Variante löscht erst den Teilstring „String“ aus dem Ursprungstext und vergleicht diesen dann mit dem ersetzten. Wenn die Texte nicht gleich sind, wurde etwas gelöscht und das bedeutet, dass der Teilstring im Ursprungstext enthalten war.
strpos() ermittelt die Position im Text, an der der gesuchte String das erste mal vorkommt und gibt diesen zurück. Falls die Funktion den String nicht findet, gibt sie false zurück (man könnte also auch statt !==false auf >0 prüfen).
Und die dritte im Bunde ist preg_match. Diese Funktion arbeitet mit einem regulären Ausdruck und gibt die Anzahl der Übereinstimmungen zurück. Da sie aber nach der ersten gefundenen Übereinstimmung abbricht, gibt es nur die Rückgabewerte 0 (keine Übereinstimmung) und 1 (Übereinstimmung gefunden).
Auswertung:
Datei | Gesamtlaufzeit | durchschnittliche Laufzeit pro Durchlauf | Verhältnis zur schnellsten Variante |
---|---|---|---|
result_find_strpos.php | 27.890104 s | 2.789 ms | 100 % |
result_find_ str_replace.php | 40.107672 s | 4.011 ms | 143 % (+43 %) |
result_find_ preg_match.php | 42.801546 s | 4.280 ms | 153 % (+53 %) |
strpos ist eindeutig die schnellste Lösung, um zu prüfen, ob ein String in einem größeren String enthalten ist. preg_match ist zwar schnell, jedoch muss die Regex-Engine genutzt werden, die für solch einfache Aktionen zu mächtig und ungeeignet ist. Die Ersetzungsvariante ist recht umständlich und anschließend muss noch der Stringvergleich durchgeführt werden – das ist nicht sehr flott.
Merke: Zum Feststellen, ob sich eine Zeichenkette in einem Text befindet, sollte strpos genutzt werden!!!
Die Quellcodes stehen ebenso zum Download zur Verfügung wie die Benchmark-Ergebnisse
Achtung !!
Bei der str_pos Variante kann es zu fehlern kommen, wenn sich der gesuchte Text direkt am Anfang befindet. Weil dann Position = 0 als false fehlinterpretiert werden könnte (und wird)
Falsch. Deshalb wird per !== und nicht != überprüft. Dadurch wird auch der Datentyp verglichen.
Es gilt
0==false aber nicht 0===false
Axel meinte wohl den Satz „(man könnte also auch statt !==false auf >0 prüfen)“.
!==false ist schon die einzig richtige Variante..
>0 geht nicht, da hier das ganze nicht funktioniert, falls der gesuchte String am Anfang steht.
Also ihr meint beide das gleiche, habt aber aneinander vorbei geredet.
„strstr“ ist nicht im Bench drin?
habe es mal nachgeholt
AMD1800+
for($i=0;$i0 prüfen)”
das geht schon ….
…. ich hänge einfach noch ein Space davor
strpos( ‚ ‚.$text , $suche )
gabs dieses !== und === schon bei C (ohne ++) früher?
Bitte schreib deinen Code mal in <pre>. WordPress filtert da sonst zu viel raus.
Hier ist, was Andy mitteilen wollte:
„strstr“ ist nicht im Bench drin?
habe es mal nachgeholt
AMD1800+
= 2.05 sec
der strpos bei mir
= 1.90 sec
Problem, Position 0 bei strpos
„(man könnte also auch statt !==false auf >0 prüfen)“
das geht schon ….
…. ich hänge einfach noch ein Space davor
strpos( ‚ ‚.$text , $suche )
gabs dieses !== und === schon bei C (ohne ++) früher?
Bei C war das !== gar nicht nötig, denn C hat ja richtige Datentypen. Da muss man doch auch Strings mit equals überprüfen, wenn ich richtig liege (arbeite desktop-mäßig nur mit Java und da ist es so).
Danke für Deinen Vorschlag. Habs jetzt nicht nochmal getestet, aber ist das Ergebnis auch so, wenn du paar mal auf Aktualisieren drückst?
ja, ich habe jedes etwa 5 mal mit [Reload]
der strpos schwankte zwischen 1.908 und 1.91
Habe es jetzt mehrfach in eine Datei zusammengefügt
strpos ……… 1.7790880203247 sec
strstr ……… 1.8908660411835 sec
strstr ……… 1.917338848114 sec
strpos ……… 1.7752649784088 sec
strpos in C war doch glaub um einzelne Zeichen zu finden, um Strings zu finden dann strstr
man könnte auch if($pos > -1) machen wenn man kein fan von !== false ist… mich ärgert das ehrlich gesagt auch sehr, php schwächelt hier.
Vielen Dank für den Artikel und den coolen Vergleich, hat mir sehr geholfen.
Hallo Jan,
Wie/Mit welchem Tool ermittelst du die Laufzeit?
[
]
Code funktioniert ja mal wieder wunderbar hier…
$old = microtime(true);
// your code
echo microtime(true) – $old;
In C gibt es keine Strings als Datentyp, sondern nur Char-Arrays, die mit terminiert werden. alle strXXX()-Funktionen funktionieren nur, wenn das -Byte gesetzt wurde.