php.de

Zurück   php.de > php.de Intern > Wiki Diskussionsforum > Tutorials

Tutorials Hier findest Du Tutorials, welche nach und nach ein fertiges Script ergeben. Sehen, lernen & verstehen!

Thema geschlossen
 
LinkBack (4) Themen-Optionen
Alt 30.09.2006, 21:24  
Erfahrener Benutzer
 
Registriert seit: 18.07.2004
Beiträge: 2.162
PHP-Kenntnisse:
Fortgeschritten
Basti
Standard Parsen von Delimitern

Tutorial von nikosch77:

Willkommen.
Dieses Tutorial beschäftigt sich mit dem Parsen von Zeichenketten.

Zielstellung:
Gegeben ist ein String, der Befehle, Tags o.ä. enthält, die wiederum Parameter definieren, die in Zeichenketten eingeschlossen sind. Als Beispiel nehmen wir eine Menge von SQL Anfragen:

Zitat:
$sql = "EXPLAIN Table; SELECT * FROM Table a WHERE a.name = 'Peter\'s Blog; A plain story';
DELETE FROM Table WHERE name = 'Foo';DELETE FROM Table WHERE name = 'Bar'";
Wir wollen nun jeden einzelnen Befehl in ein Array Element überführen. Dazu sollen z.B. Semikoleon und Zeilenumbruch als Trennzeichen (TZ) dienen.

Was zunächst simpel erscheint offenbart zwei Probleme:

1. Wir können die Zeichenkette nicht einfach am TZ auftrennen, da z.B. das Semikoleon auch innerhalb eines Eintrags des Befehls existiert. Wir müssen also diese Bereiche separat behandeln.

2. Auch diese als separat bearbeiteten Bereiche sind nicht unproblematisch, da sie beliebig viele sog. escapete Zeichen beinhalten können, die ohne \ die Zeichenkette beenden würden. Deshalb muß die Erkennung des Bereiches nicht nur 'Peter\' sondern 'Peter\'s Blog; A plain story' zurückgeben.

Herleitung:
Nach einigem Hin- und Herüberlegen stellte sich die Bruteforce Methode als die einfachste heraus: Wir gehen also den gesamten Text Fundstelle für Fundstelle durch, schneiden Teile ab und fügen diese wieder zusammen.

Wir basteln uns dazu zwei Hilfsfunktionen.

1/ explode_by_set()

entspricht weitestgehend der Funktion explode(), teilt also einen gegebenen String unter Zuhilfenahme eines Trennzeichens auf. explode_by_set() erweitert die Funktion auf die Nutzung mehrerer verschiedener TZ.

PHP-Code:

  
function explode_by_set ($separatorArray $string)
    {
    
$separatorArray = (array) $separatorArray;

    
$string str_replace($separatorArray $separatorArray[0], $string);

    return (
explode($separatorArray[0] , $string));
    } 
$separatorArray ist ein Array mit Trennzeichen, da der String $string ohnehin gleich aufgeteilt wird, werden alle TZ im String in eines aus der Menge ersetzt und dann der String per explode() aufgeteilt.
Damit sind wir in der Lage unsere obigen SQL Elemente in Befehle aufzutrennen. Bleibt das Problem mit '' begrenzten Bereichen.

2/ cut_left

Die Funktion arbeitet folgenderweise: ermittle mit strpos() das erste Auftauchen eines Suchstrings (später "'") im Text. Wenn gefunden gib den Teil von 0 bis zur Fundstelle zurück. Die Fundposition wird gespeichert. Beim nächsten Aufruf wird ab dieser Position gesucht.
Bei jedem Fund des Suchsstrings wird das Zeichen davor mit einem Escapezeichen (typischerweise "\") verglichen. Stimmen sie überein, wird an dieser Stelle nichts abgeschnitten, sondern nach dem nächsten Begrenzer gesucht. Das passiert bis zum ersten nicht escapeten Begrenzer. Bis dort wird der linke Teil der Zeichenkette zurückgegeben usw.
Findet strpos() bis zum Ende des Reststrings kein Begrenzerzeichen mehr, wird der Rest des Textes zurückgegeben, weitere Aufrufe geben anschließend nur noch false zurück.
Hier die gesamte Funktion:

PHP-Code:

  
function cut_left $string$searchString $escapeChar '' $reset false)
    {
    static 
$position;
    if (
$reset !== false$position is_numeric($reset)
                                      ? 
max ($reset 0) -1
                                      
: -1;
    if (!isset(
$position)) $position = -1;

    
$start $position 1;

    
# ---- Suchstring suchen
  
    
$position strpos ($string $searchString $start);

    
# ---- Suchstring nicht gefunden, Rest ausgeben

    
if (false===$position
      {
      if (
$position == strlen ($string) - 1) return (false);

      
$position strlen ($string) - 1;
      return (
substr($string $start));
      }

    
# --- keine Escapezeichen verwendet, Teilzeichenkette (TZK) zurückgeben

    
if (!$escapeChar)
      return (
substr ($string $start $position-$start));

    
$length $position $start;

    
# --- Escapezeichen verwendet, letztes Zeichen der TZK prüfen

    # --- kein escapter Suchstring, TZK zurückgeben
    
if ($position==|| $string{$position-1} != $escapeChar
      return (
substr ($string $start $length));

    
# --- es ist ein escapter Suchstring, rekursiv TZK um nächsten Teil erweitern
    #     dabei escapten Suchstring mitnehmen (+1)
    
else 
      return (
substr ($string $start $length 1) .
              
cut_left ($string $searchString $escapeChar)
             );
    } 
Der $reset Parameter dient nur dem Fall, daß mehrere solcher Trennaktionen erfolgen sollen,
dann kann mit einem boolschen true die Startposition auf 0 bzw. mit einem int Wert auf eine beliebige andere Position gesetzt werden.

Da diese zweite Funktion irgendwann false zurückgibt, kann sie optimal in einer Schleife eingesetzt werden.
Wichtig ist dabei ein === Vergleich, um die Schleife nicht schon bei einem leeren Stringrückgabewert zu beenden.

PHP-Code:

$sql 
"EXPLAIN Table; SELECT * FROM Table a WHERE a.name = 'Peter\'s Blog; A plain story';
DELETE FROM Table WHERE name = 'Foo';DELETE FROM Table WHERE name = 'Bar'"
;

for (
$i=0;;$i++)
  {
  
$return cut_left $sql "'" "\\");
  if (
false===$return) break;
  echo 
"\n",$return;
  } 
Schauen wir uns das resultierende Array an, haben wir schon fast die Lösung für unser Ursprungsproblem:

Zitat:
EXPLAIN Table; SELECT * FROM Table a WHERE a.name =
Peter\'s Blog; A plain story
;
DELETE FROM Table WHERE name =
Foo
;DELETE FROM Table WHERE name =
Bar
Hier stehen nämlich die Bestandteile innerhalb und außerhalb eines '' Bereichs schon jeweils in einem extra Eintrag. Und noch besser: Jeder zweite Eintrag ist stets ein ' separierter Sting, die anderen immmer Resttext. Das ist auch so, wenn unser Ausgangstext bereits mit Hochkommata beginnt, dann ist allerdings das Element 0 des Arrays leer. Anhand des Arraykeys können wir nun mit dem Modulooperator herausfinden, ob wir gerade einen geschützten Bereich bearbeiten.

Wir nutzen nun die erste Funktion und trennen Eintrag 0, 2, 4 usw. mit den angegebenen TZ auf, also Semikoleon und Zeilenumbruch:

Zitat:
Array
(
[0] => EXPLAIN Table
[1] => SELECT * FROM Table a WHERE a.name =
)
Peter\'s Blog; A plain story
Array
(
[0] =>
[1] =>
[2] => DELETE FROM Table WHERE name =
)
Foo
Array
(
[0] =>
[1] => DELETE FROM Table WHERE name =
)
Bar
Die letzte Aktion schließlich besteht darin, die ursprünglich in Hochkommata eingeschlossenen Parameter wieder in '' einzuschließen, und das ganze sinnvoll zu einem Array zu verknüpfen. Dazu füllen wir ein neues Array per Wert für Wert auf. Aus den Arrays mit aufgetrennten Befehlen fügen wir den ersten stets an den letzte Datensatz des Zielarrays an (denn die erste Trennung ist genaugenommen erst zwischen Element 0 und 1 gewünscht) - ebenso die Bereiche in '' - und fügen das restliche Array an unser Zielarray an. Das bei diesen Aktionen öfter leere Werte verarbeitet werden soll uns nicht weiter stören.
Wie wir sehen kann das Element 0 mit dem Inhalt 'EXPLAIN Table' nirgends angefügt werden, deshalb muß unser Zielarray mit einem leeren Element initialisiert werden. Dann erhalten wir:

Zitat:
Array
(
[0] => EXPLAIN Table
[1] => SELECT * FROM Table a WHERE a.name = 'Peter\'s Blog; A plain story'
[2] =>
[3] => DELETE FROM Table WHERE name = 'Foo'
[1] => DELETE FROM Table WHERE name = 'Bar'
)
Nahezu perfekt! Die eine Lücke entsteht, da zwischen "plain story';" und "DELETE " genaugenommen zwei Trennzeichen, nämlich ; und Zeilenumbruch stehen. Um dies zu beheben wird unsere Funktion 1 um einen Parameter erweitert, der per preg_replace mehrere Trennzeichen zu einem reduziert.

Die Lösung:
Hier nun das fertige Script, mit erweiterten Funktionen:

PHP-Code:

  
/*
  int = explode_by_set (mixed separators , string string [, int Flag ] )

  --------------------------------------------------------------------------- */
  
function explode_by_set ($separatorArray $string $reduce )
    {
    
# ---- explizite Typumwandlung
    
$separatorArray = (array) $separatorArray;

    
# ---- alle Trennzeichen in das erste umwandeln
    
$string str_replace($separatorArray $separatorArray[0], $string);

    
# ---- wenn gewünscht, direkt aufeinanderfolgende zu einem zusammenfassen
    
if ($reduce == 1
      
$string preg_replace('/['preg_quote($separatorArray[0]) .']+/'  
                             
$separatorArray[0]                           , 
                             
$string);

    return (
explode($separatorArray[0] , $string));
    }


  
/*
  string = cut_left ( string string , string searchString [, char escapeCharacter [, bool reset]] )

  --------------------------------------------------------------------------- */
  
function cut_left $string$searchString $escapeChar '' $reset false)
    {
    static 
$position;
    if (
$reset !== false$position is_numeric($reset)
                                      ? 
max ($reset 0) -1
                                      
: -1;
    if (!isset(
$position)) $position = -1;

    
$start $position 1;

    
# ---- Suchstring suchen
  
    
$position strpos ($string $searchString $start);

    
# ---- Suchstring nicht gefunden, Rest ausgeben

    
if (false===$position
      {
      if (
$position == strlen ($string) - 1) return (false);

      
$position strlen ($string) - 1;
      return (
substr($string $start));
      }

    
# --- keine Escapezeichen verwendet, Teilzeichenkette (TZK) zurückgeben

    
if (!$escapeChar)
      return (
substr ($string $start $position-$start));

    
$length $position $start;

    
# --- Escapezeichen verwendet, letztes Zeichen der TZK prüfen

    # --- kein escapter Suchstring, TZK zurückgeben
    
if ($position==|| $string{$position-1} != $escapeChar
      return (
substr ($string $start $length));

    
# --- es ist ein escapter Suchstring, rekursiv TZK um nächsten Teil erweitern
    #     dabei escapten Suchstring mitnehmen (+1)
    
else 
      return (
substr ($string $start $length 1) .
              
cut_left ($string $searchString $escapeChar)
             );
    }



$sql "EXPLAIN Table; SELECT * FROM Table a WHERE a.name = 'Peter\'s Blog; A plain story';
DELETE FROM Table WHERE name = 'Foo';DELETE FROM Table WHERE name = 'Bar'"
;

$delimiter  "'";
$escape        "\\";
$cutters    = array( "\r\n" ";" );


$result = array (=> '');
for (
$i=;; $i++)
  {
  
$return cut_left ($sql $delimiter $escape);
  if (
$return===false) break;

  
# ---- jeder 2. Stringpart ist eine Zeichenkette in Hochkommata

  
if (($i 2) == 1)
    
$result[count($result)-1] .= "'$return'";

  
# ---- der Rest wird nach Trennzeichen aufgeteilt 
  
else 
    {
    
$items explode_by_set ($cutters $return 1);
    
$result[count($result) -1] .= array_shift($items);
    
$result array_merge ($result $items);
    }  
  }

print_r($result); 
Basti ist offline  
Sponsor Mitteilung
PHP Code Flüsterer

Registriert seit: 21.08.2005
Beiträge: 4682
PHP-Kenntnisse:
Fortgeschritten

Thema geschlossen


Themen-Optionen


LinkBacks (?)
LinkBack to this Thread: http://www.php.de/tutorials/42326-parsen-von-delimitern.html
Erstellt von For Type Datum
broadcast This thread Refback 12.10.2012 02:28
Number Book This thread Refback 11.10.2012 22:32
Tala Monthly This thread Refback 02.10.2012 05:09
Photo parting very strong 2013, Photo embrace separation 2013, Photo parting and betraya This thread Refback 01.10.2012 22:21

Ähnliche Themen
Thema Autor Forum Antworten Letzter Beitrag
Dynamische HTML Seite parsen blaus PHP Tipps 2008 10 17.03.2008 14:44
XML parsen und Umlaute betterknower PHP Tipps 2008 6 31.12.2007 18:35
Parsen von Delimitern nikosch PHP-Fortgeschrittene 5 22.09.2006 15:24
geht das mit parsen?? Dopedouglaz PHP Tipps 2006 6 22.05.2006 14:13
Keine Endung Parsen? andy Server, Hosting und Workstations 3 07.03.2006 14:43
Datei Uploaden & Parsen PHP Tipps 2007 7 04.11.2005 20:51
XML-Datei direkt von FTP-Quelle parsen PHP-Fortgeschrittene 10 04.11.2005 16:12
text parsen mit php - tutorial gesucht PHP Tipps 2005-2 2 05.10.2005 11:44
[TEMPLATEENGINE] Problem mit dem Parsen von Arrays imported_Ben PHP-Fortgeschrittene 5 30.07.2005 11:07
Klasse oder php_xyz.dll zum Parsen einer Mail tapferesschneiderlein PHP Tipps 2005 5 20.03.2005 15:12
Suchstring parsen PHP Tipps 2005 4 04.01.2005 23:29
[RegEx] Datum/Uhrzeit parsen PHP-Fortgeschrittene 3 08.11.2004 08:58
XML parsen und Probleme mit "&"-Zeichen. PHP Tipps 2004 3 16.10.2004 13:54
[Erledigt] Parsen von Variablen aus einer MySQL Tabellenzeile Datenbanken 0 29.09.2004 14:58
XML parsen mit DOM PHP-Fortgeschrittene 2 24.09.2004 13:59

Besucher kamen über folgende Suchanfragen bei Google auf diese Seite
http://www.php.de/tutorials/42326-parsen-von-delimitern.html, php explode mehrer trennzeichen als eins behandeln, suchstring parsen, php substr trennzeichen, php trennzeichen zeilenumbruch, php preg_replace letzte fundstelle, zeichenketten parsen, seperator php, explode beliebig viele leerzeichen, parsen von, text parsen und die bereiche ersetzen php, string mehrere seperatoren php, php regular expression funktionen funde positionen, php substring explode, php inhalte zwischen zwei tags ausschneiden und in array, php trennzeichen zeilenwechsel, php explode mehrere separator, php string mehrere trennzeichen, php explode mehrere separatoren definieren, php substring trennzeichen

Alle Zeitangaben in WEZ +2. Es ist jetzt 10:02 Uhr.




Powered by vBulletin® Version 3.7.2 (Deutsch)
Copyright ©2000 - 2014, Jelsoft Enterprises Ltd.
Search Engine Optimization by vBSEO 3.2.0
Aprilia-Forum, Aquaristik-Forum, Liebeskummer-Forum, Zierfisch-Forum, Geizkragen-Forum

Creative Commons License
Dieser Inhalt ist unter einer Creative Commons-Lizenz lizenziert.