2009-05-11 6 views
3

Ich versuche, eine Protokolldatei zu analysieren, die wie folgt aussieht:Spiel überlappende Muster mit Fänger einen MATLAB regulären Ausdruck

%%%% 09-May-2009 04:10:29 
% Starting foo 
this is stuff 
to ignore 
%%%% 09-May-2009 04:10:50 
% Starting bar 
more stuff 
to ignore 
%%%% 09-May-2009 04:11:29 
... 

Dieser Auszug zwei Zeitperioden enthält Ich mag würde zu extrahieren, von den ersten Trennzeichen zum zweiten und vom zweiten zum dritten. Ich möchte einen regulären Ausdruck verwenden, um die Start- und Stoppzeiten für jedes dieser Intervalle zu extrahieren. Diese meist funktioniert:

p = '%{4} (?<start>.*?)\n% Starting (?<name>.*?)\n.*?%{4} (?<stop>.*?)\n'; 
times = regexp(c,p,'names'); 

Rückkehr:

times = 

1x16 struct array with fields: 
    start 
    name 
    stop 

Das Problem ist, dass diese erfasst nur jede zweite Periode, da der zweite Begrenzer als Teil des ersten Spiels verbraucht wird.

In anderen Sprachen können Sie Lookaround-Operatoren (Lookahead, Lookbehind) verwenden, um dieses Problem zu lösen. Die documentation on regular expressions erklärt, wie diese in MATLAB funktionieren, aber ich konnte diese nicht ausführen, während die Matches noch erfasst wurden. Das heißt, ich muss nicht nur jedes Trennzeichen abgleichen können, sondern auch einen Teil dieser Übereinstimmung (den Zeitstempel) extrahieren.

Ist das möglich?

P.S. Mir ist klar, dass ich dieses Problem lösen kann, indem ich eine einfache Zustandsmaschine schreibe oder indem ich die Begrenzer und die Nachbearbeitung anpasse, wenn es keine Möglichkeit gibt, dies zum Laufen zu bringen.

Update: Vielen Dank für die Workaround-Ideen, alle. Ich habe vom Entwickler gehört und es gibt derzeit keine Möglichkeit, dies mit der regulären Ausdrucksmethode in MATLAB zu tun.

+0

Wie sieht die letzte Zeile der Protokolldatei aus? Wird es eine "%%%% ..." Zeile mit nichts danach sein, oder hört es mit dem vorherigen zu ignorierenden Zeug auf? – gnovice

+0

Alle Begrenzerzeilen sehen gleich aus, so dass der letzte einen Zeitstempel enthält und Sie wissen lassen, wann die letzte Periode beendet wurde. Nach dem letzten Trennzeichen müssen weitere Zeilen ignoriert werden. –

Antwort

2

MATLAB scheint nicht in der Lage Zeichen als Zeichen zu erfassen, ohne sie aus dem String zu entfernen (oder soll ich sagen, ich nicht in der Lage war, dies zu tun mit MATLAB REGEXP). Wenn ich jedoch feststelle, dass die Stoppzeit für einen Textblock gleich der Startzeit des nächsten ist, konnte ich nur die Startzeiten und die Namen mit REGEXP erfassen und dann eine einfache Verarbeitung durchführen, um die Stoppzeiten von der Startzeiten Früher habe ich den folgenden Beispieltext:

c = 

%%%% 09-May-2009 04:10:29 
% Starting foo 
this is stuff 
to ignore 
%%%% 09-May-2009 04:10:50 
% Starting bar 
more stuff 
to ignore 
%%%% 09-May-2009 04:11:29 
some more junk 

... und angewandt, um den folgenden Ausdruck:

p = '%{4} (?<start>[^\n]*)\n% Starting (?<name>[^\n]*)[^%]*|%{4} (?<start>[^\n]*).*'; 

Die Verarbeitung kann dann mit dem folgenden Code durchgeführt werden:

names = regexp(c,p,'names'); 
[names.stop] = deal(names(2:end).start,[]); 
names = names(1:end-1); 

.. ., die uns diese Ergebnisse für den obigen Beispieltext gibt:

>> names(1) 

ans = 

    start: '09-May-2009 04:10:29' 
    name: 'foo' 
    stop: '09-May-2009 04:10:50' 

>> names(2) 

ans = 

    start: '09-May-2009 04:10:50' 
    name: 'bar' 
    stop: '09-May-2009 04:11:29' 
+0

Ich habe die Antikausalität des Logs behoben. Diese sollten sequenziell sein. –

0

Alles, was Sie tun sollten, müssen, ist eine Look-Ahead um den Teil der Regex wickeln, die den zweiten Zeitstempel übereinstimmt:

'%{4} (?<start>.*?)\n% Starting (?<name>.*?)\n.*?(?=%{4} (?<stop>.*?)\n)' 

EDIT: Hier ist es ohne benannte Gruppen ist:

'%{4} (.*?)\n% Starting (.*?)\n.*?(?=%{4} (.*?)\n)' 
+0

Alan, danke, dass du einen Fehler gemacht hast. Wenn ich versuche, was Sie vorschlagen (und den schließenden Teil hinzufügen), erfasst es länger die Werte. –

+0

Versuchen Sie es dann ohne benannte Gruppen. In jedem anderen Regex-Stil, den ich kenne, der Lookaheads und Capturing-Gruppen unterstützt, können Sie Dinge in einem Lookahead erfassen. Aber vielleicht lässt MATLAB das nicht zu. –

+0

Auch ohne benannte Gruppen zu verwenden, scheint es immer noch nicht zu funktionieren. Ich denke, MATLAB hat Schwierigkeiten, die Token-/Gruppierungsoperationen und die Lookahead-Operationen gleichzeitig zu lösen. – gnovice

1

Wenn Sie tun viel Parsing und solche Arbeit, könnten Sie in Betracht ziehen, Perl from within Matlab zu verwenden. Es ermöglicht Ihnen den Zugriff auf die leistungsstarke Regex-Engine von Perl und kann auch viele andere Probleme einfacher lösen.