EisFuX: preg_match(), preg_split()

Beitrag lesen

(Hallo|Hi(ho)|Tag) Jo,

habe folgende Aufgabe: Ich extrahiere aus Header dem von Bildern umfangreiche Informationen und dabei kommt sowas als Textstring raus:

Driver: GTiff/GeoTIFF
Size is 6400, 9600
Pixel Size = (10.00000000,-10.00000000)
Metadata:
TIFFTAG_SOFTWARE=Adobe Photoshop CS Windows
TIFFTAG_RESOLUTIONUNIT=2 (pixels/inch)
Corner Coordinates:
Upper Left ( 44000.000, 142000.000)
Upper Right ( 108000.000, 142000.000)
Overviews: 3200x4800, 1600x2400, 800x1200, 400x600, 200x300
usw...

Nun möchte ich immer die Metainformationen zwischen zwei Ausdrücken extrahieren.
z.B. zwischen "Driver:" und "Size is" = "GTiff/GeoTIFF"
oder zwischen "Size is " und "Pixel Size" = "6400, 9600"
usw.

Hierzu würde ich preg_match() etwa so einsetzen:

  
$offset = 0;  
// schleife  
  // $rx muss natuerlich in jedem Durchgang anders aufgebaut sein  
  $rx = '/(Driver:)(.*?)(?Size is)/s';  
  if ( !preg_match($rx, $text, $treffer, PREG_OFFSET_CAPTURE, $offset) ) {  
    // Fehlerbehandlung  
    ...  
    break;  
  }  
  // gefunden  
  // in $treffer[1] steht der gesuchte "Zwischentext"  
  ...  
  $offset = $treffer[1][1] + strlen( $treffer[1][0] );  
// ende_der_schleife  

Die erste Klammer enthält ein gewöhnliches Suchmuster und umgeht so das
(eventuell auftretende) Problem mit Lookbehind-Assertions, die in
PHPs-PCRE derzeit nur feste Längen haben dürfen.

Wie gehe ich dabei am besten vor? Mit regulären Ausdrücken?

Am liebsten zerlege ich solche Meta-Daten-Listen mit preg_split().
Allerdings sollte der Text dazu "strukturierter" aufgebaut sein.

Wenn dein Text wirklich so unstrukturiert aufgebaut ist, dann kommst du
mit einem einzelnem RegEx wahrscheinlich nicht sehr weit. Das einzige
Muster, was ich hier sehe, ist der Zeilenumbruch. Prinzipiell könnte man
den Text zuerst mit
$zeilen = preg_split('/(\r\n|[\r\n])/', $dein_text);
in einzelne Zeilen zerlegen.

Danach wirds aber schwierig, da es kein einheitliches Trennzeichen (und
auch keine einheitliche Trennzeichenfolge) zwischen den "Bezeichnern" und
den folgenden Daten gibt. Wenn es das gäbe, könntest du einfach nochmal mit
preg_split() drübergehen. Aber so musst du für jede Zeile ein eigenes Muster
finden.

Beispiele:

  
// Driver: GTiff/GeoTIFF  
list($k, $v) = preg_split('/:/', $zeile, 2);  
// Size is 6400, 9600  
list($k, $v) = preg_split('/(?<is)\s+/', $zeile, 2);  
// Pixel Size = (10.00000000,-10.00000000)  
list($k, $v) = preg_split('/\s+=\s+/', $zeile, 2);  

Wenn du die Metadaten selbst aus den Bilddateien rausholst, könntest du
auch eine Ebene tiefer ansetzen, anstatt den formatierten Text zu zerlegen,
der ja selbst aus den Metadaten gewonnen wurde.

MffG
EisFuX