Portal > Foren > PHP > PHP-Programmierung > [RegExp] einzelnes Zeichen wird (unverständlicherweise) gematcht
Antwort
 
Themen-Optionen Thema durchsuchen
Alt 06.11.2006, 02:50 Nach oben    #1
Ben
Benjamin Klaile
 
Benutzerbild von Ben
 
Registriert seit: 02.12.2004
Ort: Remagen
Beiträge: 4.480
Standard [RegExp] einzelnes Zeichen wird (unverständlicherweise) gematcht

Hi,
ich werd noch wahnsinnig. Sorry für den bescheuerten Titel.

Ich habe folgendes Pattern:
Code:
([a-zA-Z-]+)\/{0,1}([a-zA-Z-]+)\/([\d]+),([\w-]+)
Damit möchte ich Zeichenketten dieser Form "parsen".
Code:
kategorie/1,das-ist-ein-titel
rubrik-demo/sektion/4312,toller-titel
Wenn ich das Pattern auf zweite Zeichenkette anwende erhalte ich das hier
Code:
array(5) {
  [0]=>
  array(1) {
    [0]=>
    string(37) "rubrik-demo/sektion/4312,toller-titel"
  }
  [1]=>
  array(1) {
    [0]=>
    string(11) "rubrik-demo"
  }
  [2]=>
  array(1) {
    [0]=>
    string(7) "sektion"
  }
  [3]=>
  array(1) {
    [0]=>
    string(4) "4312"
  }
  [4]=>
  array(1) {
    [0]=>
    string(12) "toller-titel"
  }
}
Sauber. Passt.

Wenn ich es auf den ersten String anwende erhalte ich das hier
Code:
array(5) {
  [0]=>
  array(1) {
    [0]=>
    string(29) "kategorie/1,das-ist-ein-titel"
  }
  [1]=>
  array(1) {
    [0]=>
    string(8) "kategori"
  }
  [2]=>
  array(1) {
    [0]=>
    string(1) "e"
  }
  [3]=>
  array(1) {
    [0]=>
    string(1) "1"
  }
  [4]=>
  array(1) {
    [0]=>
    string(17) "das-ist-ein-titel"
  }
}
Ich raff es nicht.
Ich bin der absolute Laie was reguläre Ausdrücke angeht, aber man muss ja auch mal was neues lernen, gell?

Das Pattern mal auseinandergenommen, so wie ich das verstehe:
  • ([a-zA-Z-]+)\/{0,1}([a-zA-Z-]+)\/
    = bedeutet, dass entweder "text/" oder "text/tralala" (eventuell mit "-") vorkommen kann.
    So ganz sicher bin ich mir jetzt gar nicht mehr, warum ich bei der ersten Gruppe ein "+" und beim ersten / ein {0,1} hingeschrieben hab
  • ([\d]+),([\w-]+)
    = bedeutet, dass zuerst eine oder mehrere Ziffern vor einem Komma kommt und danach irgendwas alphanumerisches inkl. "-"

Hm, kann mir wer sagen, wieso da das letzte Zeichen separat ausgelesen wird?
Danke.

Grüße, Ben.


[EDIT]
Getestet natürlich mit dem regex-tester(.de)
Ben ist offline  
Add Post to del.icio.usBookmark Post in TechnoratiDiesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 06.11.2006, 07:47 Nach oben    #2
Erfahrener Benutzer
 
Registriert seit: 18.03.2005
Beiträge: 591
Standard

Soweit ich das um 7:30 Uhr sehe, ist die zweite Zeile vom Aufbau her, genau wie die erste Zeile, nur mit einen Zusätzlichen Wert davor.

So auf die Schnelle:
http://www.regex-tester.de/regex_20061106072945.html

bzw.:
Code:
(?:([\w\-]+)/)?([\w\-]+)/(\d+),([\w\-]+)
Um es einfacher zu machen, habe ich jetzt mal bewusst nur \w (Zeichenklasse für [A-Za-z0-9_]) benutzt.
Den Modifer i hab ich versehend mit eingebaut, was bei \w nicht benötigt wird.

Bei deiner zweiten Zeile steht noch zusätzlich rubrik-demo/ da.
Damit dies, sagen wir mal optinal ist, dient dieser Bereich:
Code:
(?:([\w\-]+)/)?
Dabei bedeutet das ?: so grob gesagt, schreibe nur etwas in das Array, wenn auch was gefunden wird.
Ich weis nicht wie weitere solcher Zeilen von dir aussehen, aber es könnte passieren du musst dies wieder rausnehmen, wenn du gezielt auf das Array-Ergebnis zugreiffen willst.

Das abschliessende ? hinter ( ... ) bedeutet nur, dass dieser String vorkommen kann, aber nicht muss.

Noch etwas:
Code:
[\w\-]
Das Minuszeichen habe ich mit Absicht extra markiert.
Muss nicht unbedingt sein, sollte man sich aber angewöhnen.
Das Minuszeichen steht eigentlich für einen Bereich von-bis.
Also a-z => von a bis z
Folgender Ausdruck würde sonst nicht gehen:
[a-cm-]

Willst du dein Pattern etwas eingrenzen:
Code:
(?:([a-z\-]+)/)?([a-z\-]+)/([0-9]+),([a-z\-]+)
Und dann mit Modifer i.

So Kaffee trinken ...
CIX88 ist offline  
Add Post to del.icio.usBookmark Post in TechnoratiDiesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 06.11.2006, 12:03 Nach oben    #3
Johannes Schlichenmaier
 
Benutzerbild von Jojo
 
Registriert seit: 26.08.2005
Ort: Mannheim
Beiträge: 398
Standard

Wofür dient genau das ?: ?
Also, wieso benötigt man es?

Ich habe mal ein wenig rumprobiert und bin auf die selbe Antwort auf die Frage, aber auf diese Lösung gekommen:
Code:
([a-zA-Z-]+\/)?([a-zA-Z-]+)\/([\d]+)\,([\w-]+)
wobei man um das erste [a-zA-Z]+ bei Bedarf noch Klammern setzten kann, um das / auszuschließen....

Danke im vorraus für die Erklärung
Jojo
__________________
In the beginning was the word
and the word was content-type: plain/text

heute code ich, morgen debug ich und uebermorgen cast ich die koenigin auf int
Jojo ist offline  
Add Post to del.icio.usBookmark Post in TechnoratiDiesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 06.11.2006, 12:26 Nach oben    #4
Bastian Fenske
 
Registriert seit: 04.01.2006
Ort: Kassel
Beiträge: 826
Standard

Hi.

Es wurden ja bereits Lösungen genannt, allerdings scheint mir der Part nach dem ersten optionalen Slash (hier: /section) optional zu sein und nicht der Part davor. Daher würde ich eben auch diesen als optional definieren und nicht den Part vor dem Slash, wie in den hier gezeigten Lösungen.

Von vorne:

Zitat:
Zitat von Ben Beitrag anzeigen
Ich habe folgendes Pattern:
Code:
([a-zA-Z-]+)\/{0,1}([a-zA-Z-]+)\/([\d]+),([\w-]+)
[...]
Hm, kann mir wer sagen, wieso da das letzte Zeichen separat ausgelesen wird?
Klar: Die Anweisung lautet: Suche mir ein oder mehr Buchstaben (als ersten Block), gefolgt von einem oder keinem Slash und weiteren 1-n Buchstaben (als zweiten Block).

Im ersten String den du testest gibt es diesen Slash nicht. Bleiben also zwei Blöcke mit je 1-n Buchtaben übrig. Um dieses Suchmuster für "kategorie" zu erfüllen wird dieser String nun also zerlegt in zwei Blöcke, die die Muster erfüllen. Das könnte letztlich alles zwischen k-ategorie und kategori-e sein und preg_match nimmt eben letztere Möglichkeit.

Um das zu verhindern musst du einfach den Teil "Optionaler Slash gefolg von 1-n Buchstaben" als Option angeben:

Code:
([a-zA-Z-]+)(?:/{0,1}([a-zA-Z-]+)?)/([\d]+),([\w-]+)
...natürlich noch escapen.

Basti

Geändert von Basti (06.11.2006 um 12:33 Uhr).
Basti ist offline  
Add Post to del.icio.usBookmark Post in TechnoratiDiesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 06.11.2006, 12:27 Nach oben    #5
Erfahrener Benutzer
 
Registriert seit: 18.03.2005
Beiträge: 591
Standard

Zitat:
Wofür dient genau das ?: ?
Den Unterschied sieht man am Resultat, was dann im Array steht.
Ganz einfach ausgedrückt, mit ?: nach etwas suchen, aber nicht zusätzlich dazu ein Array-Eintrag machen.
CIX88 ist offline  
Add Post to del.icio.usBookmark Post in TechnoratiDiesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 06.11.2006, 12:41 Nach oben    #6
Ben
Benjamin Klaile
 
Benutzerbild von Ben
 
Registriert seit: 02.12.2004
Ort: Remagen
Beiträge: 4.480
Standard

Wow. Danke. Gute Antworten sind das.
Habe CIXs Pattern verwendet, aber ich hätte - nach meinem Verständnis - auch Bastis nehmen können. Klappen beide wunderbar.

Danke für die Erläuterungen.
Hier das verstehe ich aber noch nicht ganz
Zitat:
Zitat von Basti
gefolgt von einem oder keinem Slash und weiteren 1-n Buchstaben (als zweiten Block).
Hm, wieso denn 1-n Buchstaben? Wo habe ich das denn angegeben?

Danke.
Grüße, Ben.
Ben ist offline  
Add Post to del.icio.usBookmark Post in TechnoratiDiesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 06.11.2006, 12:58 Nach oben    #7
Bastian Fenske
 
Registriert seit: 04.01.2006
Ort: Kassel
Beiträge: 826
Standard

Das "+" steht für mindestens 1 mal.

Zu den Unterschieden der beiden Varianten nochmal:
PHP-Code:
<?php

$sPatterns
[0] = "(?:([a-z\-]+)/)?([a-z\-]+)/([0-9]+),([a-z\-]+)";
$sPatterns[1] = "([a-z\-]+)(?:/{0,1}([a-z\-]+)?)/([\d]+),([a-z\-]+)";

$sTests[0] = "kategorie/1,das-ist-ein-titel";
$sTests[1] = "rubrik-demo/sektion/4312,toller-titel";

foreach (
$sPatterns as $sPattern) {

    echo 
$sPattern":\n";
    foreach (
$sTests as $sTest) {
        
preg_match("|$sPattern|i"$sTest$aMatches);
        
var_dump($aMatches);
        echo 
"\n";
    }
    echo 
"\n";
}
?>
Code:
(?:([a-z\-]+)/)?([a-z\-]+)/([0-9]+),([a-z\-]+:(

array
  0 => 'kategorie/1,das-ist-ein-titel' (length=29)
  1 => '' (length=0)
  2 => 'kategorie' (length=9)
  3 => '1' (length=1)
  4 => 'das-ist-ein-titel' (length=17)

array
  0 => 'rubrik-demo/sektion/4312,toller-titel' (length=37)
  1 => 'rubrik-demo' (length=11)
  2 => 'sektion' (length=7)
  3 => '4312' (length=4)
  4 => 'toller-titel' (length=12)

([a-z\-]+)(?:/{0,1}([a-z\-]+)?)/([\d]+),([a-z\-]+:(

array
  0 => 'kategorie/1,das-ist-ein-titel' (length=29)
  1 => 'kategorie' (length=9)
  2 => '' (length=0)
  3 => '1' (length=1)
  4 => 'das-ist-ein-titel' (length=17)

array
  0 => 'rubrik-demo/sektion/4312,toller-titel' (length=37)
  1 => 'rubrik-demo' (length=11)
  2 => 'sektion' (length=7)
  3 => '4312' (length=4)
  4 => 'toller-titel' (length=12)
Einmal hast du also 'kategorie' in $aMatches[1] und einmal in $aMatches[2]. Ist halt die Frage, was du brauchst.

Basti
Basti ist offline  
Add Post to del.icio.usBookmark Post in TechnoratiDiesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 06.11.2006, 13:11 Nach oben    #8
Ben
Benjamin Klaile
 
Benutzerbild von Ben
 
Registriert seit: 02.12.2004
Ort: Remagen
Beiträge: 4.480
Standard

Zitat:
Zitat von Basti Beitrag anzeigen
Das "+" steht für mindestens 1 mal.
Oh Gott. Ich hab n-1 gelesen und 1-n geschrieben. ...
Jau. Danke.
Danke auch für die Zusammenstellung der beiden Varianten.

Merke: Ich sollte mich intensiver damit beschäftigen. Klingt alles ganz interessant.

Grüße, Ben.
Ben ist offline  
Add Post to del.icio.usBookmark Post in TechnoratiDiesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 06.11.2006, 14:55 Nach oben    #9
Johannes Schlichenmaier
 
Benutzerbild von Jojo
 
Registriert seit: 26.08.2005
Ort: Mannheim
Beiträge: 398
Standard

Zitat:
Zitat von CIX88 Beitrag anzeigen
Zitat:
Wofür dient genau das ?: ?
Den Unterschied sieht man am Resultat, was dann im Array steht.
Ganz einfach ausgedrückt, mit ?: nach etwas suchen, aber nicht zusätzlich dazu ein Array-Eintrag machen.
Merci,
das hab ich gebraucht
__________________
In the beginning was the word
and the word was content-type: plain/text

heute code ich, morgen debug ich und uebermorgen cast ich die koenigin auf int
Jojo ist offline  
Add Post to del.icio.usBookmark Post in TechnoratiDiesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 06.11.2006, 17:27 Nach oben    #10
Erfahrener Benutzer
 
Registriert seit: 18.03.2005
Beiträge: 591
Standard

Nunja, das ganze mit ?: hat erst Sinn, wenn Gruppierungen (runde Klammern) vorhanden sind.

Beispiel:

Code:
(B[a-z]+)
Mit preg_match() oder preg_match_all() würde das Ergebnis mehrere Einträge im Array erzeugen.

Code:
(?:B[a-z]+)
Jetzt wird die Ausage regelrecht verkürzt.

?: bezieht sich immer auf eine Gruppierung (runde Klammern).
Diese Zeile ist demnach falsch.
Code:
?:B[a-z]+
CIX88 ist offline  
Add Post to del.icio.usBookmark Post in TechnoratiDiesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 06.11.2006, 18:22 Nach oben    #11
Ben
Benjamin Klaile
 
Benutzerbild von Ben
 
Registriert seit: 02.12.2004
Ort: Remagen
Beiträge: 4.480
Standard

Das mit ?: hat mir sehr weitergeholfen.
Auch von mir ein "Danke".
Ben ist offline  
Add Post to del.icio.usBookmark Post in TechnoratiDiesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Antwort

Lesezeichen


Aktive Benutzer in diesem Thema: 1 (Registrierte Benutzer: 0, Gäste: 1)
 
Themen-Optionen Thema durchsuchen
Thema durchsuchen:

Erweiterte Suche

Forumregeln
Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Ähnliche Themen
Thema Autor Forum Antworten Letzter Beitrag
[Notepad++]UTF-8 setzt Zeichen an Dateianfang WarrenFaith Tools, Server, Betriebssysteme 2 21.01.2007 18:02


Alle Zeitangaben in WEZ +2. Es ist jetzt 06:50 Uhr.


Powered by vBulletin® Version 3.7.3 (Deutsch)
Copyright ©2000 - 2008, Jelsoft Enterprises Ltd.
Search Engine Optimization by vBSEO 3.2.0

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44