Regular Expressions
Tom
- php
Hello,
in einem längeren Text befindet sich eine Startsignatur mehrfach und die Abschlusssignatur des gesuchten Bereiches nur einmal.
xxxxxxxxxxxxxxxx
xxxxxxxxxxxxxSTARTxxxxxxxxxxxxxxx
xxxSTARTxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxSTARTsssssssssss
sssssssss
ssssssssssssssSTOPxxxxxxx
xxxxxxxxxxxxxxxxxx
STARTxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxx
sss wird gesucht.
Wie muss ich das machen, dass ich nur den Bereich vom letzten Vorkommen von START vor STOP bis STOP bekomme?
Ich habe jetzt diverse Versuche mit Greedyness, Assertions usw. durch und komme auf keinen Lösungsweg.
Dabei kann ich die Positionen eindeutig identifiziern, könnte es also mit "Drumherumprogrammierung" auch lösen.
$_total_matches = array();
$offset = 0;
while (preg_match($pattern1, $content, $_matches, PREG_OFFSET_CAPTURE, $offset))
{
$_lastmatch = end($_matches);
$offset = $_lastmatch[1] + strlen($_lastmatch[0]);
$_total_matches[] = $_lastmatch;
}
Ich würde nur gerne wissen, ob man für diesen Fall nicht doch eine Regular Expression finden kann.
Liebe Grüße aus dem schönen Oberharz
Tom vom Berg
Folgende regex (PCRE) sollte es funktionieren. Hab ich auch getestet.
START([^STAR]*)STOP
START (sammle alle daten die nicht gleich der Startsequenz sind bis) STOP
Hello,
Folgende regex (PCRE) sollte es funktionieren. Hab ich auch getestet.
START([^STAR]*)STOP
START (sammle alle daten die nicht gleich der Startsequenz sind bis) STOP
Nur, dass [^STAR] eine Zeichenklasse darstellt, die alle _Zeichen_ akzeptiert, die nicht 'S' oder 'T' oder 'A' oder 'R' sind. Reihenfolge und Anzahl sind dabei vollkommen egal.
'Finde nicht Zeichenkette' gibt es mWn auch nicht bei Regular Expressions.
Liebe Grüße aus dem schönen Oberharz
Tom vom Berg
Hello Tom,
in einem längeren Text befindet sich eine Startsignatur mehrfach und die Abschlusssignatur des gesuchten Bereiches nur einmal.
xxxxxxxxxxxxxxxx
xxxxxxxxxxxxxSTARTxxxxxxxxxxxxxxx
xxxSTARTxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxSTARTsssssssssss
sssssssss
ssssssssssssssSTOPxxxxxxx
xxxxxxxxxxxxxxxxxx
STARTxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxsss wird gesucht.
Wie muss ich das machen, dass ich nur den Bereich vom letzten Vorkommen von START vor STOP bis STOP bekomme?
Ich habe jetzt diverse Versuche mit Greedyness, Assertions usw. durch und komme auf keinen Lösungsweg.
Dabei kann ich die Positionen eindeutig identifiziern, könnte es also mit "Drumherumprogrammierung" auch lösen.
Willst du es jetzt unbedingt mit RegExp machen?
Hier erschiene mir eine Lösung mit strpos(), strrpos() und substr() nämlich vermutlich viel einfacher.
Gruß Gunther
Hello,
in einem längeren Text befindet sich eine Startsignatur mehrfach und die Abschlusssignatur des gesuchten Bereiches nur einmal.
xxxxxxxxxxxxxxxx
xxxxxxxxxxxxxSTARTxxxxxxxxxxxxxxx
xxxSTARTxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxSTARTsssssssssss
sssssssss
ssssssssssssssSTOPxxxxxxx
xxxxxxxxxxxxxxxxxx
STARTxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxsss wird gesucht.
Wie muss ich das machen, dass ich nur den Bereich vom letzten Vorkommen von START vor STOP bis STOP bekomme?
Ich habe jetzt diverse Versuche mit Greedyness, Assertions usw. durch und komme auf keinen Lösungsweg.
Dabei kann ich die Positionen eindeutig identifiziern, könnte es also mit "Drumherumprogrammierung" auch lösen.
Willst du es jetzt unbedingt mit RegExp machen?
Ja. Wenn es geht, möchte ich gerne wissen, wie.
Hier erschiene mir eine Lösung mit strpos(), strrpos() und substr() nämlich vermutlich viel einfacher.
Wenn Du auf das Muster dort oben anspielst, das ist eben nur ein Muster.
RegExp muss ich sowieso einsetzen. Wie oft die Startsequenz vorkommt weiß ich nicht, was x un s für Zeichen sind, weiß ich auch nicht vorher...
Liebe Grüße aus dem schönen Oberharz
Tom vom Berg
Hello again,
Ja. Wenn es geht, möchte ich gerne wissen, wie.
Hier erschiene mir eine Lösung mit strpos(), strrpos() und substr() nämlich vermutlich viel einfacher.
Wenn Du auf das Muster dort oben anspielst, das ist eben nur ein Muster.
RegExp muss ich sowieso einsetzen. Wie oft die Startsequenz vorkommt weiß ich nicht, was x un s für Zeichen sind, weiß ich auch nicht vorher...
ich bin leider alles andere als ein Profi in Sachen RegExp, aber vielleicht kommst du mit den Stichwörtern ja auch alleine weiter.
Wenn dann würde ich mal annehmen, dass du hier
Hope it helps.
Gruß Gunther
Hello,
- (?(condition)...|...) / (?(condition)...) if-then-else / if-then pattern
Condition habe ich noch nicht untersucht, ob das helfen kann...
Schau ich mir mal an
Liebe Grüße aus dem schönen Oberharz
Tom vom Berg
(H[ae]llo|Hi(ho)|Nabend) Tom,
xxxxxxxxxxxxxxxx
xxxxxxxxxxxxxSTARTxxxxxxxxxxxxxxx
xxxSTARTxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxSTARTsssssssssss
sssssssss
ssssssssssssssSTOPxxxxxxx
xxxxxxxxxxxxxxxxxx
STARTxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxx
sss wird gesucht.
Wie muss ich das machen, dass ich nur den Bereich vom letzten Vorkommen von START vor STOP bis STOP bekomme?
Ist dir preg_match('/\A.+START(.+?)(?=STOP)/s', $content, $_matches) zu einfach?
Das liefert in $_matches[1] den gewünschten Teilstring. Falls dir nicht gefällt, dass
auch noch etwas mehr gefunden wird, nimmst du halt
preg_replace('/\A.+START(.+?)(?=STOP).+\z/s', '$1', $content)
Ich habe jetzt diverse Versuche mit Greedyness, Assertions usw. durch und komme auf keinen Lösungsweg.
preg_match('/(?<=START)(.(?!START))+?(?=STOP)/s', $content, $_matches)
schaut zwar nicht sehr elegant aus, liefert aber das gewünschte Ergebnis.
Dabei kann ich die Positionen eindeutig identifiziern, könnte es also mit "Drumherumprogrammierung" auch lösen.
Warum versuchst du es dann mit Regulären Ausdrücken?
Soll das eine Knobelaufgabe werden? ;-)
MffG
EisFuX
Nachtrag
... Falls dir nicht gefällt, dass
auch noch etwas mehr gefunden wird, nimmst du halt
preg_replace('/\A.+START(.+?)(?=STOP).+\z/s', '$1', $content)
preg_replace('/\A.+START(.+?)STOP.+\z/s', '$1', $content)
tut es natürlich auch, ganz ohne "komplizierte" Assertions
(die einfachen "\A" und "\z" bleiben aber).
MffG
EisFuX
Hello,
Wie muss ich das machen, dass ich nur den Bereich vom letzten Vorkommen von START vor STOP bis STOP bekomme?
Ist dir preg_match('/\A.+START(.+?)(?=STOP)/s', $content, $_matches) zu einfach?
Das liefert in $_matches[1] den gewünschten Teilstring. Falls dir nicht gefällt, dass
auch noch etwas mehr gefunden wird, nimmst du halt
preg_replace('/\A.+START(.+?)(?=STOP).+\z/s', '$1', $content)
Könntest Du bitte nochmal 'was zu \A und \z sagen.
Ist das identisch mit ^ und $?
bei PHP steht leider nur "The simple assertions coded as \b, \B, \A, \Z, \z, ^ and $ are described above" und above ist (noch) nichts zu finden. Liegt wohl am Umbau der Seiten.
http://de2.php.net/manual/en/regexp.reference.assertions.php
Und Wiki schweigt sich dazu ganz aus.
http://de.wikipedia.org/wiki/Regulärer_Ausdruck
Warum versuchst du es dann mit Regulären Ausdrücken?
Soll das eine Knobelaufgabe werden? ;-)
Nö, sollte es nicht, ist es aber inzwischen geworden.
Es geht dann noch weiter. Block (.+?) enthält jetzt mehrere Paare von Parametern, die ich eigentlich haben will.
Mit Stringfunktionen, explode() und einfachen RegExp habe ich das Ergebnis ja schon, aber nun hat mich der Ehrgeiz gepackt, aus ca. 40 Zeilen Programm eine Zeile Pattern zu machen...
Nachdem Du mir gezeigt hast, dass der erste Teil funktioniert, bin ich sicher, dass der zweite auch noch klappt :-)
Liebe Grüße aus dem schönen Oberharz
Tom vom Berg
Hello,
Könntest Du bitte nochmal 'was zu \A und \z sagen.
Ist das identisch mit ^ und $?
Ok, ich denke, ich hab's gefunden
Soll eine Zeichenkette nur aus dem gesuchten Muster bestehen (und es nicht nur enthalten), so muss in den meisten Implementierungen explizit definiert werden, dass das Muster von Anfang (\A oder ^)1 bis zum Ende der Zeichenkette (\Z, \z oder $)1 reichen soll, ansonsten matcht zum Beispiel [0-9]{2,5} auch bei der Zeichenkette „1234507“ die Teilzeichenkette „12345“. Aus dem gleichen Grund würde bspw. a* immer matchen, da jeder String, selbst der leere „“, mind. 0-mal das Zeichen „a“ enthält. 1Die Zeichen ^ und $ matchen im multiline-Modus (d. i. wenn der m-Modifier gesetzt wird) auch Zeilenanfänge und -enden.
Nur die weitere Zerlegung krieg ich noch nicht hin.
Liebe Grüße aus dem schönen Oberharz
Tom vom Berg
(H[ae]llo|Hi(ho)?|Mahlzeit) Tom,
Könntest Du bitte nochmal 'was zu \A und \z sagen.
Ist das identisch mit ^ und $?
Manchmal.
\A und \z verankern ein Suchmuster immer jeweils am Anfang und am Ende der gesamten Zeichenkette.
Die Bedeutung von ^ und $ als "Anker" hängt vom Multiline-Modifikator m ab. Der ist mir zu
blöd, wenn ich Zeilenumbrüche erkennen will, verlasse ich mich lieber auf (\r\n|[\r\n]).
bei PHP steht leider nur "The simple assertions coded as \b, \B, \A, \Z, \z, ^ and $ are described above" und above ist (noch) nichts zu finden. Liegt wohl am Umbau der Seiten.
http://de2.php.net/manual/en/regexp.reference.assertions.php
Letztendlich schreibt man dort nur von der offiziellen Dokumentation ab.
Der passende Abschnitt für ^ und $ dürfte der hier sein:
PCRE_MULTILINE
By default, PCRE treats the subject string as consisting of a single
line of characters (even if it actually contains newlines). The "start
of line" metacharacter (^) matches only at the start of the string,
while the "end of line" metacharacter ($) matches only at the end of
the string, or before a terminating newline (unless PCRE_DOLLAR_ENDONLY
is set). This is the same as Perl.When PCRE_MULTILINE it is set, the "start of line" and "end of line"
constructs match immediately following or immediately before internal
newlines in the subject string, respectively, as well as at the very
start and end. This is equivalent to Perl's /m option, and it can be
changed within a pattern by a (?m) option setting. If there are no new-
lines in a subject string, or no occurrences of ^ or $ in a pattern,
setting PCRE_MULTILINE has no effect.
Und Wiki schweigt sich dazu ganz aus.
http://de.wikipedia.org/wiki/Regulärer_Ausdruck
Die Homepage auf pcre.org verweist explizit auf den PCRE-Artikel in der englischprachigen Wikipedia.
Also würde ich lieber da nachschauen.
MffG
EisFuX