2012-04-13 12 views
0

Meine Frage ist ein wenig wortreich, also werde ich versuchen, es mit einem Beispiel zu erklären.Wie kann ich eine Zeichenfolge in Perl aufteilen, die Trennzeichen beibehalten und die Trennung zwischen den Trennzeichen sein?

Ich habe eine Datei, die etwas ähnlich zu XML ist, die ich analysieren muss, wenn auch nicht genau. Elemente in der Datei zeigen in der Regel nach oben ähnlich wie XML-Format, wie

<person><greeting>hello</greeting><goodbye>bye</goodbye></person> 

ich die Datei in einzelne Sätze von Tags aufteilen wollte, so dass ein Element

<greeting>hello</greeting> 

wäre und ein anderer wäre

<goodbye>bye</goodbye> 

natürlich für ein leeres Element, <person> und </person> ihre eigenen Elemente am Ende werden, bin ich damit völlig in Ordnung, weil die wie ich die Datei als Ganzes analysieren möchte.

Das Problem, das ich renne, ist, wie man die ganze Datei am besten in ein Array aufteilt, weil es in der Datei überhaupt keine Zeilenumbrüche gibt, es wird so geschrieben, wie man es sieht. Ich habe versucht, es zu tun wie diese

my @array = split(/(><)/, $file) 

aber das Problem ist, dass es nicht die Winkel Klammern als Teil des zugehörigen Tages nicht erhalten, sondern trennt sie aus. Gibt es eine Möglichkeit für mich, die Datei zwischen die> und < Zeichen zu teilen?

+0

Wenn Ihre Datei nahe genug an XML ist, warum nicht einfach einen XML-Parser verwenden? – Gabe

+0

Im Grunde sind das Hausaufgaben oder nahe genug dazu. Es ist eine Übung in regulären Ausdrücken, nicht im XML-Parsing, und wir wurden ermutigt, die XML-Bibliotheken nicht zu verwenden. –

Antwort

3

Ich bin nicht sicher, ob dies die beste Lösung ist, aber um Ihre Frage direkt zu beantworten, können Sie zwischen den Winkeln unter Verwendung lookbehind and lookahead assertions teilen.

my @array = split(/(?<=>)(?=<)/, $file) 

Der Unterschied ist. dass sie den >< Teil nicht konsumieren, passen sie die Position dazwischen an.

Eine weitere Idee wäre, eine Rückreferenzierung zu verwenden, um die richtigen zu entsprechen (es entspricht den ersten Closing-Tag mit diesem Namen, das ist falsch, wenn identische Tags verschachtelt sind) schließender Tag, so etwas wie dieser

<([^>]*)>(.*?)</\1> 

See es here on Regexr

Sie haben zwei Referenzen in diesem Regex. Die erste wird verwendet, um das schließende Tag zu finden, und in der zweiten finden Sie den Inhalt des Tags.

Natürlich wird zuerst das "person" -Tag übereinstimmen, aber Sie finden die anderen Tags in $2. Sie müssten die Regex rekursiv auf $ 2 verwenden, bis das Ergebnis ein leeres Array ist.

+0

Dies scheint fast perfekt zu funktionieren, aber es scheint, als ob zwischen jedem vollständigen Element leere Elemente eingefügt werden. –

+0

@DanielSarder Die (nicht benötigte) Erfassungsgruppe um die Regex hat die leeren Elemente im Array verursacht. Korrigierte meine Antwort. – stema

Verwandte Themen