Schrift
[thread]10767[/thread]

patern matching

Leser: 1


<< |< 1 2 >| >> 11 Einträge, 2 Seiten
olruebe01
 2007-11-10 13:40
#102172 #102172
User since
2006-01-19
192 Artikel
BenutzerIn
[default_avatar]
Hallo Forum,

mir liegt mal wieder ein Stein im Weg...

Ich habe einen ewig langen Text (in $content) und möchte nun den kürztmöglichen Satz finden, der mit "Haus" gebinnt, mit "Zaun" endet und es muss "Wiese" und "Garten" dazwischen vorkommen (in der Reihenfolge).

Zwischen diesen 4 Wörtern können beliebig viele Zeichen sein aber es soll das kürztmögliche Ergebnis gefunden werden.

Anfangs gucke ich erstmal, ob mein Kriterium überhaupt erfüllt wird.

Meine Idee:
Code: (dl )
if($content =~ /<Haus.*Wiese.*Garten.*Zaun/) { print "ja";}


Klappt soweit auch. Aber jetzt komme ich nicht weiter. Wie kann ich mir den ganzen Satz ausgeben lassen, also print...?

Zweites Problem: Was ist, wenn meine Text über mehrere Zeilen geht? Mein obige Beispiel geht nur, solange der zu suchende Text in der selben Zeile gefunden wird.
Der . steht ja für "irgendein Zeichen ausßer Newline". Also habe ich dies probiert:
Code: (dl )
if($content =~ /Haus[.\n]*Zaun/) { ...}

Gedanke: Finde "Haus", dann irgendein Zeichen außer Newline (Punkt) oder Newline und das auch mehrmals. Aber das war auch nichts...

Ich habe auch noch andere Versuche gestartet aber alle waren Fruchtlos.

Schonmal Danke für Eure Hilfe.
olruebe01
 2007-11-10 14:37
#102174 #102174
User since
2006-01-19
192 Artikel
BenutzerIn
[default_avatar]
Die Frage nach der Ausgabe konnte ich mir inzwischen selber beantworten.
Wenn ich die Abfrage in runde Klammern setze, kann ich über $1 den gesamten gefundenen Teil abrufen.

Bleibt die Frage, wie ich ich die Abfrage von gierig in bescheiden ändern kann und wie ich über einen mehrzeiligen Text suchen kann...
Linuxer
 2007-11-10 17:17
#102179 #102179
User since
2006-01-27
3890 Artikel
HausmeisterIn

user image
Hi,

* ist gierig (greedy), *? ist nicht gierig (non-greedy)
+ ist gierig, +? ist nicht gierig

http://perldoc.perl.org/perlretut.html#Matching-re...
meine Beiträge: I.d.R. alle Angaben ohne Gewähr und auf Linux abgestimmt!
Die Sprache heisst Perl, nicht PERL. - Bitte Crossposts als solche kenntlich machen!
Linuxer
 2007-11-10 17:21
#102180 #102180
User since
2006-01-27
3890 Artikel
HausmeisterIn

user image
Code (perl): (dl )
1
2
3
4
5
$str = "Mein Haus,\nmein Boot,\nmein Garten,\nmeines Nachbarn Zaun.\nUnd ein anderer Zaun, der hier nix zu suchen hat.";

if ( $str =~ m/(Mein.+?Garten.+?Zaun.)/s ) {
print "ja: $1\n";
}


Quote
ja: Mein Haus,
mein Boot,
mein Garten,
meines Nachbarn Zaun.

Die Verwendung des /s-Modifiers macht es möglich.

http://perldoc.perl.org/perlre.html
meine Beiträge: I.d.R. alle Angaben ohne Gewähr und auf Linux abgestimmt!
Die Sprache heisst Perl, nicht PERL. - Bitte Crossposts als solche kenntlich machen!
olruebe01
 2007-11-10 19:04
#102184 #102184
User since
2006-01-19
192 Artikel
BenutzerIn
[default_avatar]
Hi Linuxer,

danke erstmal. /s-Modifier nach hinten... Das hatte ich nicht versucht. ICh habe immer vorne rumgedocktert.

Den Punkt gierig habe ich inzwischen auch schon rausgefunden. Das das was mit gierig zu tun hat, war mir klar. Nur wusste ich nicht, wie ich dies ändern kann.

Was aber jetzt noch mein Problem ist:
Was ist, wenn der Anfang (Haus) mehrmals auftaucht.

Beispiel:
Code: (dl )
1
2
3
4
5
1: $str = "Dein Haus, dein Boot, \nmein Haus,\nmein Boot,\nmein Garten,\nmeines Nachbarn Zaun.\nUnd ein anderer Zaun, der hier nix zu suchen hat.";
2:
3: if ( $str =~ m/(Haus.+?Garten.+?Zaun.)/s ) {
4: print "ja: $1\n";
5: }


Ich möchte quasi das GARTEN gefunden wird und aus dem nächstmöglichen "Haus" davor und "Zaun" danach soll der kürzeste mögliche Satz gebildet werden. Also das erste Haus muss ignoriert werden (in diesem Falle). Der Satz soll bei dem letzten "Haus" vor "Garten" anfangen (in diesem Falle also das zweite Haus).

Wenn aber vorher 49 mal Haus im Text vorkommt, soll auch erst das 49. Haus als Satzanfang genommen werden.

Wie mache ich das???

Das Wort GARTEN kommt übrigens nur ein Mal in meinem Text vor. Das ist sicher.
moritz
 2007-11-10 19:20
#102185 #102185
User since
2007-05-11
923 Artikel
HausmeisterIn
[Homepage]
user image
Du könntest z.B. mit CPAN:Regexp::Exhaustive nach allen matches suchen, und nur den kürzesten Match nehmen. Könnte halt ziemlich ineffizient werden...
olruebe01
 2007-11-12 09:22
#102229 #102229
User since
2006-01-19
192 Artikel
BenutzerIn
[default_avatar]
HI Moritz,

dieses Modul steht mir anscheinend nicht zur Verfügung und ichkann sowas nicht selber installieren...

Ich habe es jetzt mit einer While-Schleife gelöst.
Code: (dl )
1
2
3
4
5
6
while ($str=~ m/Haus.+?Haus.+?Garten.+?Zaun/s ) { 
$str=~ s/Haus//;
if ( $str=~ m/(Haus.+?Garten.+?Zaun)/s ) {
$str= $1;
}
}


So lange also vor Garten und Zaun 2x(!) "Haus" vorkommt, wird das erste "Haus" entfernt und die matching-abfrage durchgeführt. So wird $1 runden für runde ums erste "Haus" gebracht, bis nurnoch ein Mal "Haus" vor den anderen Wörtern bleibt.

Vielleicht noch nicht die eleganteste Lösung, läuft aber.

Jetzt habe ich noch ein Problem:
Wenn der Text nicht von mir ist, sondern per UserAgent von einem anderen Server geladen wird, scheinen da unichtbare teuerzeichen oder owas drin zu sein.

Die erkennungdes Textes funktioniert. Es wird über mehrere Zeilen der kürzeste Satz gefunden. Perfekt. Aber wenn ich nun diesen kürzesten Satz per
Code: (dl )
$content=~ s/$str//;

entfernen will, geschieht das nicht. Sehe ich mir den originaltext und den kurzen Satz an, sind die augenscheinlich absolut identisch.

Der lange Text wird von einem anderen Server generiert (auch mein Skript). Aber ich kann hier nichts erkennen, was ich da falsch gemacht haben könnte.

Fällt Euch auf Anhieb etwas ein, was ich prüfen könnte? Könnte der Text irgendwei ander formatiert werden, nachdem ich ihn per UerAgent lade?
renee
 2007-11-12 09:52
#102232 #102232
User since
2003-08-04
14371 Artikel
ModeratorIn
[Homepage] [default_avatar]
olruebe01+2007-11-12 08:22:11--
HI Moritz,

dieses Modul steht mir anscheinend nicht zur Verfügung und ichkann sowas nicht selber installieren...


Wieso nicht? Das eigentliche Modul ist eine einfach .pm-Datei, genau wie Du sie auch schreiben würdest...
OTRS-Erweiterungen (http://feature-addons.de/)
Frankfurt Perlmongers (http://frankfurt.pm/)
--

Unterlagen OTRS-Workshop 2012: http://otrs.perl-services.de/workshop.html
Perl-Entwicklung: http://perl-services.de/
pq
 2007-11-12 10:06
#102238 #102238
User since
2003-08-04
12208 Artikel
Admin1
[Homepage]
user image
olruebe01+2007-11-12 08:22:11--
dieses Modul steht mir anscheinend nicht zur Verfügung und ichkann sowas nicht selber installieren...

weit gefehlt...
Wiki:ModuleWieInstalliereIchEinModul
Always code as if the guy who ends up maintaining your code will be a violent psychopath who knows where you live. -- Damian Conway in "Perl Best Practices"
lesen: Wiki:Wie frage ich & perlintro Wiki:brian's Leitfaden für jedes Perl-Problem
olruebe01
 2007-11-12 20:49
#102296 #102296
User since
2006-01-19
192 Artikel
BenutzerIn
[default_avatar]
Ok, ich ändere meine Aussage: Ich habe bisher noch nie ein Modul installiert und bei jeder Anleitung habe ich recht schnell den Faden verloren.
<< |< 1 2 >| >> 11 Einträge, 2 Seiten



View all threads created 2007-11-10 13:40.