regex über mehrere Zeilen

r0bby

Grünschnabel
Hallo Leute,

Ich möchte eine XML Datei einlesen und diese bearbeiten.
Es sollen z.B. alle Zeilen und die dazugehörigen Tags gelöscht werden in denen ein bestimmtes Wort enthalten ist.

Bsp: falls "World" vorkommt so soll das ganze Topic gelöscht werden.

<Topic r:id="Top/Arts">
<catid>2</catid>
<aolsearch>art</aolsearch>
<dispname>Arts and Entertainment</dispname>
<d:Title>Arts</d:Title>
<altlang r:resource="Afrikaans:Top/World/Afrikaans/Kuns"/>
<altlang r:resource="Albanian:Top/World/Shqip/Art"/>
<altlang r:resource="Armenian:Top/World/Armenian/Ô±Ö€Õ¸Ö‚Õ¥Õ½Õ¿"/>
</Topic>

Nun habe ich das einigermaßen mit regulären Ausdrücken hinbekommen.
Java:
[...]
String abc=".*World.*";
Pattern pattern=Pattern.compile(abc);
[...]

Leider ist die Lösung nicht ganz korrekt da nun nur die Zeilen gelöscht werden welche das Wort "World" enthalten. Es soll jedoch das komplette Topic gelöscht werden!
Dies sollte ja eigentlich mit Zeilenumbrüchen funktionieren.
Bsp:
[...]
String abc="<Topic.*\nWorld.*\n</Topic>";
Pattern pattern=Pattern.compile(abc);
[...]

Leider ist das nicht der Fall! Ich bekomme es leider überhaupt nicht hin dem Programm zu erlären dass es da mehrere Zeilenumbrüche gibt und dass es sogar eine beliebige Anzahl davon geben könnte.

Kann mir da jemand helfen? Gibt es überhaupt einen Ausdruck für beliebige Zeilenumbrüche wie \n* !?

-Danke
 
Ich weiss nicht, obs in der Sprache auch Flags gibt.... normalerweise findet der Punkt in RegExp keine Zeilenumbrüche...mit der Flag "s" findet er auch diese.
 
Ok, Danke erstmal.

Das DOTALL Flag wird in Java mit einem (?s) bezeichnet. Leider bringt die Anwednung ebenfalls Probleme mit sich.
Falls ich nun foldenden Code eingebe, so werden alle Ausdrücke (auch solche, die alleine stehen) gelöscht.

String abc="(?s)<Topic.*World.*</Topic>";
Pattern pattern=Pattern.compile(abc);

d.h in der Datei werden nun alle Ausdrücke welche nur "<Topic" oder nur "World" beinhalten gelöscht!

Am ende habe ich dann eine komplett leere Datei :(

Weißt du wie ich das korrigiere?
Vielleicht mit und-Verknüpfungen? (&&)
z.B.
String abc="(?s)<Topic.*&&.*World.*&&.*</Topic>";
 
Zuletzt bearbeitet:
Ich kann das Problem nun etwas besser beschreiben.

Folgenden Code habe ich angewendet:

String abc="<hallo.*wie.*^</hallo>";
Pattern pattern=Pattern.compile(abc,Pattern.MULTILINE&Pattern.DOTALL);

Bei dieser Datei läuft alles optimal: (hallo1.rdf)
[...]
<hallo> wie gehts </hallo> <!-- diese Zeile wird gelöscht-->

<test> irgendein Text </test> <!-- diese Zeile wird nicht gelöscht -->

<hallo> nochmal </hallo> <!-- diese Zeile wird nicht gelöscht -->
[...]

Bei dieser Datei nicht: (hallo2.rdf)
[...]
<hallo> wie gehts
</hallo>

<test> irgendein Text </test>

<hallo> nochmal </hallo>

<!--alle Zeilen werden gelöscht einschließlich "<test> [...] </test>" und "<hallo> nochmal </hallo>" -->
[...]

Nun verstehe ich nicht an was das jetzt liegt. Nur falls ein Zeilenumbruch vorkommt, so werden ALLE Zeichen gelöscht und falls dieser nicht vorkommt werden nur die richtigen Zeichen gelöscht?

Ist das irgendwie ein Memory Problem? Also kann sich Java nach einem Zeilenumbruch nicht mehr merken dass der Ausdruck aus "<hallo>.*wie.*</hallo>" besteht und stattdessen alles abgrast bis das letzte </hallo> gefunden wurde?

Falls ich übrigens
Pattern pattern=Pattern.compile(abc,Pattern.MULTILINE|Pattern.DOTALL);
vrewende, so tritt das Problem immer auf, egal ob Zeilenumbrüche verwendet werden oder nicht.

Danke nochmal im Vorraus!!
 
Zuletzt bearbeitet:
Ok, ich bin selber darauf gestoßen wie man diesen "Fehler" behebt.
Das Stichwort lautet non-greedy matching.

Das Problem bei meinem Code war dass er auf greedy eingestellt war. Das heißt dass das Programm bis zum nächsten "</hallo>" so viele Zeichen wie möglich verbraucht hatte. (Dies währe somit das letzte "</hallo>")

Um nun so wenig Zeichen wie möglich zu verbrauchen muss man das non-greedy matching aktivieren. Hierfür setzt man nach .* ein ?. Somit erhält man den Ausdruck (.*?)
Bsp:

String abc="<hallo(.*?)hallo(.*?)</hallo>";
Pattern pattern=Pattern.compile(abc,Pattern.DOTALL|Pattern.MULTILINE);

(Quelle: http://www.coding-board.de/board/archive/index.php/t-10797.html)

Danke an alle die mir geholfen haben!
 

Neue Beiträge

Zurück