Textdatei zeilenweise nach Suchbegriffen mit PHP und der Funktion strpos durchsuchen
27.05.2011
19:11:38 Uhr3382 Aufrufe
3 Antworten
19:11:38 Uhr
3 Antworten
Hilfreich +2
Da schon mal der Wunsch auftaucht(e), eine Textdatei mittels Script (Batch, PHP, VBS etc. . . .) nach Begriffen zu durchsuchen, und dabei auch
Schwierigkeiten bestehen/bestanden, das Ergebnis von strpos auszuwerten, habe ich das jetzt mal hier wie folgt mit PHP und strpos umgesetzt.
Schwierigkeiten bestehen/bestanden, das Ergebnis von strpos auszuwerten, habe ich das jetzt mal hier wie folgt mit PHP und strpos umgesetzt.
Das Script nimmt zwei Parameter entgegen:
- Den Namen einer Textdatei (Auswahl mit Select-Box)
- Ein oder mehrere Suchbegriffe in einem Textfeld
Bei Aufruf wird ein im Script angegebenes Verzeichnis incl. Unterverzeichnisse ausgelesen. Die Dateitypen, die eingelesen werden sollen, können hier
durch Angabe der Dateiendung bestimmt werden. Die Datei, die durchsucht werden soll, kann dann mittels einer Select-Box ausgewählt werden (Ein bißchen Komfort).
Mittels zwei verschachtelten while-Schleifen wird die Textdatei nun durchsucht. Die äußere Schleife spricht dabei alle Zeilen einer Textdatei an,
die innere Schleife alle eingegebenen Suchbegriffe. Bei jedem Durchlauf der äußeren Schleife wird also geprüft, ob sich ein oder mehrere,
eingegebene Suchbegriffe in dieser Zeile befinden. Bei jedem Fund wird eine Zeile in einem Array abgelegt, die folgendes beinhaltet:
- den gefundenen Suchbegriff
- die Zeilennummer
- die Positionsnummer in der Zeile
- die Textzeile
Auch wenn nur das Fragment eines Wortes eingegeben wurde (z.B. genaue Schreibweise nicht bekannt), wird das Fragment innerhalb eines Wortes in einer
Zeile gefunden. Somit wird auch diese Zeile ausgegeben.
Einigen PHP-Funktionen steht das Zeichen @ voran. Dadurch werden funktionseigene Fehlermeldungen unterdrückt, die durch eigene Fehlerroutinen
ersetzt werden (können).
Das Array $limiter_arr enthält Zeichen wie "+, -, &, ;" usw., die normalerweise in Suchmaschinen benutzt werden, um Suchbegriffe zu trennen, zu verknüpfen oder
auszugrenzen etc.. Diese Zeichen werden im Script durch ein Komma ersetzt. Weitere Zeichen bitte selber ins Array schreiben.
Wäre natürlich reizvoll, das Script so zu optimieren, dass Suchbegriffe verknüpft bzw. ausgegrenzt werden können.
Suchergebnisse von strpos auswerten
Suchergebnisse sollten laut http://de2.php.net/manual/de/function.str ... mit dem Operator === ausgewertet werden.
Erklärung zu diesem Operator ==> http://de2.php.net/manual/de/language.ope ...
Und los geht's . . .
. . . und End' is'.
Gruß
Günni
- Den Namen einer Textdatei (Auswahl mit Select-Box)
- Ein oder mehrere Suchbegriffe in einem Textfeld
Bei Aufruf wird ein im Script angegebenes Verzeichnis incl. Unterverzeichnisse ausgelesen. Die Dateitypen, die eingelesen werden sollen, können hier
durch Angabe der Dateiendung bestimmt werden. Die Datei, die durchsucht werden soll, kann dann mittels einer Select-Box ausgewählt werden (Ein bißchen Komfort).
Mittels zwei verschachtelten while-Schleifen wird die Textdatei nun durchsucht. Die äußere Schleife spricht dabei alle Zeilen einer Textdatei an,
die innere Schleife alle eingegebenen Suchbegriffe. Bei jedem Durchlauf der äußeren Schleife wird also geprüft, ob sich ein oder mehrere,
eingegebene Suchbegriffe in dieser Zeile befinden. Bei jedem Fund wird eine Zeile in einem Array abgelegt, die folgendes beinhaltet:
- den gefundenen Suchbegriff
- die Zeilennummer
- die Positionsnummer in der Zeile
- die Textzeile
Auch wenn nur das Fragment eines Wortes eingegeben wurde (z.B. genaue Schreibweise nicht bekannt), wird das Fragment innerhalb eines Wortes in einer
Zeile gefunden. Somit wird auch diese Zeile ausgegeben.
Einigen PHP-Funktionen steht das Zeichen @ voran. Dadurch werden funktionseigene Fehlermeldungen unterdrückt, die durch eigene Fehlerroutinen
ersetzt werden (können).
Das Array $limiter_arr enthält Zeichen wie "+, -, &, ;" usw., die normalerweise in Suchmaschinen benutzt werden, um Suchbegriffe zu trennen, zu verknüpfen oder
auszugrenzen etc.. Diese Zeichen werden im Script durch ein Komma ersetzt. Weitere Zeichen bitte selber ins Array schreiben.
Wäre natürlich reizvoll, das Script so zu optimieren, dass Suchbegriffe verknüpft bzw. ausgegrenzt werden können.
Suchergebnisse von strpos auswerten
Suchergebnisse sollten laut http://de2.php.net/manual/de/function.str ... mit dem Operator === ausgewertet werden.
Erklärung zu diesem Operator ==> http://de2.php.net/manual/de/language.ope ...
Und los geht's . . .
01.
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> 02.
<html> 03.
<head> 04.
<title>Worte in Textdateien suchen</title> 05.
</head> 06.
<body> 07.
<?php 08.
/* 09.
* Callbackfunktion mit Sortierkriterien, wird von usort benötigt 10.
*/ 11.
function cmp($a, $b) { 12.
if ($a == $b) return 0; 13.
return ($a > $b)? 1 : -1; 14.
} 15.
16.
/* 17.
* Ein Array zur Aufnahme der Dateien 18.
*/ 19.
$datei_arr=array(); 20.
21.
/* 22.
* Die Funktion liest ein Verzeichnis incl. Unterverzeichnisse aus. 23.
* - $verzeichnis - das soll ausgelesen werden 24.
* - &$arr - hier wird das Array (s.o.) übergeben. Das & ist eine Referenz auf die Variable, 25.
* die hier durch direkt von der Funktion verändert wird. 26.
*/ 27.
function dir_rekursiv($verzeichnis, &$arr){ 28.
/* 29.
* Diese Dateitypen sollen eingelesen werden. 30.
*/ 31.
//$datei_typ_arr=array(0 => ".txt", 1 => ".php", 2 => ".htm", 3 => ".html"); 32.
$datei_typ_arr=array(0 => ".txt"); 33.
$handle = @opendir($verzeichnis); 34.
while ($datei =@readdir($handle)){ 35.
if ($datei != "." && $datei != ".." ){ 36.
if (is_dir($verzeichnis.$datei)){ 37.
dir_rekursiv($verzeichnis.$datei."/", &$arr); 38.
}else{ 39.
/* 40.
* strrchr(string $string, string $zeichen) gibt den Text nach dem letzten Vorkommen von $zeichen incl. $zeichen zurück. 41.
*/ 42.
$ext=strrchr($verzeichnis.$datei, "."); 43.
/* 44.
* Wenn $ext in dem Dateitypen-Array vorkommt, Datei im Array ablegen. 45.
*/ 46.
if(in_array($ext, $datei_typ_arr)){ 47.
$arr[]=$verzeichnis.$datei; 48.
} 49.
} 50.
} 51.
} 52.
@closedir($handle); 53.
} 54.
/* 55.
* Funktionsaufruf mit Verzeichnisangabe und Variable 56.
*/ 57.
dir_rekursiv("/www/",$datei_arr); 58.
59.
/* 60.
* usort($array, Callback-Funktion) sortiert das Array. 61.
*/ 62.
usort ($datei_arr, 'cmp'); 63.
?> 64.
<!-- 65.
Ein Formular zur Eingabe. 66.
/--> 67.
<form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="post"> 68.
<p>Datei auswählen <select name="seldatei" title="Datei auswählen"></p> 69.
<option selected value=""> -- Datei auswählen -- </option> 70.
<?php 71.
/* 72.
* Dateinamen in der Selectbox ausgeben. 73.
*/ 74.
foreach($datei_arr as $datei){ 75.
echo "<option value=\"$datei\">$datei</option>"; 76.
} 77.
?> 78.
<p></select></p> 79.
<p>Suchbegriff(e) eingeben <input type="text" name="suche" title="Geben sie einen oder mehrere Suchbegriff(e) ein"></p> 80.
<p><input type="submit" name="cmd" value="Suchen" title="Absenden"></p> 81.
</form> 82.
<?php 83.
/* 84.
* Mit ini_set(PARAMETER) werden Fehler/Hinweise angezeigt. 85.
*/ 86.
ini_set('error_reporting', E_ALL|E_STRICT); 87.
ini_set('display_errors', 'On'); 88.
/* 89.
* Parameter der Funktion: 90.
* - ein oder mehrere Suchbegriffe 91.
* - einen Dateinamen 92.
*/ 93.
function findwort($wort,$textdatei){ 94.
/* 95.
* Wenn kein Dateiname eingegeben ist, Array mit Meldung füllen und beenden. 96.
*/ 97.
if(strlen(trim($textdatei))==0){ 98.
$gef_zeilen_arr[]="Wählen sie einen Dateinamen"; 99.
return $gef_zeilen_arr; 100.
} 101.
/* 102.
* Wenn kein(e) Suchbegriff(e) vorhanden sind, Array mit Meldung füllen und beenden. 103.
*/ 104.
if(strlen(trim($wort))==0){ 105.
$gef_zeilen_arr[]="Geben sie einen oder mehrere Suchbegriff(e) ein"; 106.
return $gef_zeilen_arr; 107.
} 108.
/* 109.
* Falls ein User (aus Versehen oder "zum Testen") Trennzeichen eingibt wie +, - & usw., 110.
* werden diese durch ein Komma ersetzt. Die Liste $limiter_arr nach Bedarf erweitern. 111.
*/ 112.
$limiter_arr=array(0 => "+", 1 => ";", 2 => "|", 3 => "&", 4 => " "/* Auch Leerzeichen durch Komma ersetzen */, 5 => "-"); 113.
foreach($limiter_arr as $limiter){ 114.
$wort=str_replace($limiter, ",", $wort); 115.
} 116.
/* 117.
* Suchbegriffe in $wort in einem Array ablegen. 118.
* Enthält $wort nur ein Wort, hat das Array eben nur ein Element. 119.
*/ 120.
$wort_arr=explode(",",trim($wort)); 121.
/* 122.
* Textdatei zeilenweise in ein Array einlesen. 123.
* 160 ist die Zeilenlänge, erhöhen falls nötig. 124.
*/ 125.
$text_zeilen_arr=array(); 126.
$f = @fopen($textdatei,"r"); 127.
/* 128.
* Wenn die Textdatei nicht geöffnet werden konnte (z.B. fehlende Rechte), Array mit Meldung füllen und beenden. 129.
*/ 130.
if(!$f){ 131.
$gef_zeilen_arr[]="Datei: ".$textdatei; 132.
$gef_zeilen_arr[]="Die Datei ".$textdatei." konnte nicht geöffnet werden"; 133.
return $gef_zeilen_arr; 134.
} 135.
while($zeile=@fgets($f,160)){ 136.
$text_zeilen_arr[]=$zeile; 137.
} 138.
@fclose($f); 139.
/* 140.
* Zeilenweise das Array mit der Funktion strpos durchsuchen. 141.
* strpos arbeitet case-sensitiv, deshalb werden mit strtolower 142.
* alle Groß- in Kleinbuchstaben umgewandelt. 143.
*/ 144.
$gef_zeilen_arr=array(); 145.
$gef_zeilen_arr[]="Datei: ".$textdatei; 146.
$i=0; 147.
while($i<count($text_zeilen_arr)){//while 1 148.
$k=0; 149.
/* 150.
* In der inneren Schleife wird nun Wort für Wort geprüft, ob es in der Textzeile vorkommt. 151.
*/ 152.
while($k<count($wort_arr)){//while 2 153.
$pos = @strpos(strtolower($text_zeilen_arr[$i]),strtolower($wort_arr[$k])); 154.
/* 155.
* Bitte den Operator "===" beachten. 156.
*/ 157.
if($pos === false){ 158.
/* 159.
* Wenn strpos das boolsche FALSE zurückgibt, passiert nichts. 160.
*/ 161.
}else{ 162.
/* 163.
* Ansonsten die Array-Zeile mit einer Meldung füllen. 164.
* - ($i+1) - Da ein Array bei 0 beginnt, wird eine 1 aufaddiert, weil sonst die falsche Zeilennummer am Bildschirm ausgegeben würde. 165.
* - ($pos+1) - Da strpos bei 0 anfängt zu zählen, wird eine 1 aufaddiert, weil sonst die falsche Positionsnummer am Bildschirm ausgegeben würde. 166.
*/ 167.
$gef_zeilen_arr[]="Der Suchbegriff ".$wort_arr[$k]." wurde in Zeile ".($i+1)." an Position ".($pos+1)." gefunden ==> ".$text_zeilen_arr[$i]; 168.
} 169.
$k++; 170.
}//end while 2 171.
$i++; 172.
}//end while 1 173.
/* 174.
* Enthält das Array mind. 2 Elemente(den Dateinamen und eine oder mehr gefundene Textzeilen), so wird das Array zurückgegeben. 175.
* Ansonsten wird das Array mit einer Meldung gefüllt und zurückgegeben. 176.
*/ 177.
if(count($gef_zeilen_arr)>1){ 178.
return $gef_zeilen_arr; 179.
}else{ 180.
$gef_zeilen_arr[]="Der/die Suchbegriff(e) \"$wort\" wurde(n) nicht gefunden"; 181.
return $gef_zeilen_arr; 182.
} 183.
} 184.
/* 185.
* Ist das Formular gesendet, gibt die Funktion ein Array zurück, deshalb mit foreach ausgeben. 186.
*/ 187.
if(isset($_POST['suche'])){ 188.
$erg_arr=findwort($_POST['suche'],$_POST['seldatei']); 189.
foreach($erg_arr as $erg){ 190.
/* 191.
* Die gefundenen Textzeilen mit der Funktion htmlspecialchars ausgeben, falls die durchsuchte Textdatei 192.
* eine HTML/PHP - oder ähnliche Datei ist. 193.
*/ 194.
echo "<pre>".htmlspecialchars($erg)."</pre>"; 195.
} 196.
} 197.
?> 198.
</body> 199.
</html>. . . und End' is'.
Gruß
Günni
TsukiSan schreibt am 28.05.2011 um 17:20:21 Uhr
Hallo Günni,
erst einmal vielen Dank, für deine Anleitung! Die wird sicher vielen von Nutzen sein, die mit PHP arbeiten.
deswegen auch ein hilfreich von mir
Aber, da du VBS und Co erwähnst: das läßt sich mit weniger Zeilen auch erfassen.
Ganz kurzes Bespiel:
Mich persönlich erschlägt der Code etwas. Aber eventuell liegt es daran, dass ich von PHP keine Ahnung habe.
Viele Grüße
Tsuki
erst einmal vielen Dank, für deine Anleitung! Die wird sicher vielen von Nutzen sein, die mit PHP arbeiten.
deswegen auch ein hilfreich von mir
Aber, da du VBS und Co erwähnst: das läßt sich mit weniger Zeilen auch erfassen.
Ganz kurzes Bespiel:
01.
SuchText = LCase("Im vbarchiv gibt es jede Menge Tipps und jede Menge Infos.") 02.
SuchZeichen = LCase("gibt") 03.
04.
for i = 1 to len(Suchtext) 05.
temp = mid(Suchtext,i,Len(SuchZeichen)) 06.
if temp = SuchZeichen then temp1 = temp1 & i & vbcrlf 07.
next 08.
09.
msgbox temp1Viele Grüße
Tsuki
Günni schreibt am 29.05.2011 um 09:52:40 Uhr
Hi TsukiSan,
danke für dein Feedback. Auch in meinem Script ist der eigentliche Suchvorgang nur ein paar Zeilen lang,
nimmt man die Kommentarzeilen mal raus . . .
Der Grund für die zwei while-Schleifen ist der, dass man mehrere Suchbegriffe eingeben kann, und jede Textzeile nach diesen Begriffen durchsucht wird. Die Suche nach
"vb tipp info" in der Zeile "Im vbarchiv gibt es jede Menge Tipps und jede Menge Infos." z.B. hätte dann zur Folge, dass diese Zeile zusammen mit einem der Suchbegriffe
dreimal ausgegeben wird. Das Script liest außerdem ein Verzeichnis samt Unterverzeichnisse aus, sortiert die Dateinamen und stellt diese in einer select-Box zur Auswahl dar,
damit man den Dateinamen nicht eintippen muß. Der Rest sind halt Fehlerbehandlung etc.. Ich wollte halt nicht nur die Funktion strpos erklären, das kann man selber hier
http://de2.php.net/manual/de/function.str ... nachlesen, sondern eine Anwendung vorstellen, die auch zur Inspiration dienen kann. Man könnte z.B. dieses Script so umschreiben,
dass die Seiten eines Projekts durchsucht werden, um dann, statt die gef. Zeilen auszugeben, z.B. eine Linkliste auf Projektseiten zu generieren.
Danke auch für dein "hilfreich".
Gruß, schönen Sonntag
Günni
danke für dein Feedback. Auch in meinem Script ist der eigentliche Suchvorgang nur ein paar Zeilen lang,
nimmt man die Kommentarzeilen mal raus . . .
01.
<?php 02.
$i=0; 03.
while($i<count($text_zeilen_arr)){//while 1 04.
$k=0; 05.
/* 06.
* In der inneren Schleife wird nun Wort für Wort geprüft, ob es in der Textzeile vorkommt. 07.
*/ 08.
while($k<count($wort_arr)){//while 2 09.
$pos = @strpos(strtolower($text_zeilen_arr[$i]),strtolower($wort_arr[$k])); 10.
/* 11.
* Bitte den Operator "===" beachten. 12.
*/ 13.
if($pos === false){ 14.
/* 15.
* Wenn strpos das boolsche FALSE zurückgibt, passiert nichts. 16.
*/ 17.
}else{ 18.
/* 19.
* Ansonsten die Array-Zeile mit einer Meldung füllen. 20.
* - ($i+1) - Da ein Array bei 0 beginnt, wird eine 1 aufaddiert, weil sonst die falsche Zeilennummer am Bildschirm ausgegeben würde. 21.
* - ($pos+1) - Da strpos bei 0 anfängt zu zählen, wird eine 1 aufaddiert, weil sonst die falsche Positionsnummer am Bildschirm ausgegeben würde. 22.
*/ 23.
$gef_zeilen_arr[]="Der Suchbegriff ".$wort_arr[$k]." wurde in Zeile ".($i+1)." an Position ".($pos+1)." gefunden ==> ".$text_zeilen_arr[$i]; 24.
} 25.
$k++; 26.
}//end while 2 27.
$i++; 28.
}//end while 1 29.
?>Der Grund für die zwei while-Schleifen ist der, dass man mehrere Suchbegriffe eingeben kann, und jede Textzeile nach diesen Begriffen durchsucht wird. Die Suche nach
"vb tipp info" in der Zeile "Im vbarchiv gibt es jede Menge Tipps und jede Menge Infos." z.B. hätte dann zur Folge, dass diese Zeile zusammen mit einem der Suchbegriffe
dreimal ausgegeben wird. Das Script liest außerdem ein Verzeichnis samt Unterverzeichnisse aus, sortiert die Dateinamen und stellt diese in einer select-Box zur Auswahl dar,
damit man den Dateinamen nicht eintippen muß. Der Rest sind halt Fehlerbehandlung etc.. Ich wollte halt nicht nur die Funktion strpos erklären, das kann man selber hier
http://de2.php.net/manual/de/function.str ... nachlesen, sondern eine Anwendung vorstellen, die auch zur Inspiration dienen kann. Man könnte z.B. dieses Script so umschreiben,
dass die Seiten eines Projekts durchsucht werden, um dann, statt die gef. Zeilen auszugeben, z.B. eine Linkliste auf Projektseiten zu generieren.
Danke auch für dein "hilfreich".
Gruß, schönen Sonntag
Günni
Günni schreibt am 05.06.2011 um 19:14:52 Uhr
Hallo!
Änderungen im Script.
Im Dateitypenarray die Dateiendungen mit Punkt angeben.
Statt strpos wird nun strrchr verwendet. strpos(string $string, -3) findet
so nur die letzten 3 Zeichen, bei der Endung html also nur tml.
Gruß
Günni
Änderungen im Script.
Im Dateitypenarray die Dateiendungen mit Punkt angeben.
Zeile 31:
$datei_typ_arr=array(0 => ".txt", 1 => ".php", 2 => ".htm", 3 => ".html");
$datei_typ_arr=array(0 => ".txt", 1 => ".php", 2 => ".htm", 3 => ".html");
Statt strpos wird nun strrchr verwendet. strpos(string $string, -3) findet
so nur die letzten 3 Zeichen, bei der Endung html also nur tml.
ab Zeile 40:
/*
$ext=strrchr($verzeichnis.$datei, ".");
/*
- strrchr(string $string, string $zeichen) gibt den Text nach dem letzten Vorkommen von $zeichen incl. $zeichen zurück.
$ext=strrchr($verzeichnis.$datei, ".");
Gruß
Günni







