Lange Regular Expressions beim Parsen "umbrechen"?

Begonnen von A.Harrenberg, 30 Januar 2016, 12:14:18

Vorheriges Thema - Nächstes Thema

A.Harrenberg

Hi Rudi,

ich implementiere gerade eine weitere CommandClass (4e SCHEDULE_ENTRY_LOCK) und steh' vor dem Problem die Parameter für die SET Befehle zu parsen. Das sind jede Menge Datums- und Zeitangaben. Um hier die Usereingabe zu parsen und auf (halbwegs) vernünftige Werte zu prüfen ergeben sich recht lange pattern für die Regular Expressions.

Du möchtest ja die Zeilenbreite im Code auf 80 Zeichen begrenzen, daher mal eine allgemeine Frage:

Wie kann man so lange regular expressions "umbrechen"??
m/([01]) ([0-2]?[0-9]?[0-9]) ([0-2]?[0-9]?[0-9]) ([a-z]{3}) ([0-2]?[0-9]):([0-5]?[0-9]) ([0-2]?[0-9]):([0-5]?[0-9])/)
Die Zeile in Perl einfach umzubrechen "zerstört" das pattern und funktioniert daher nicht, ich finde aber auch in der Syntax für RegExp nichts passendes.
Tante Google und die "Kurz & Gut" Version von O'Reilly schweigen sich zu dem Thema ebenfalls aus, bzw. in dem Wust der Beitrage wie man "newline" in einer Suchstring findet geht das unter...

Das kommt bisher nicht so oft vor (nur in mfsParse und "meinen" Funktionen), aber gerade die Schedule Funktionen haben doch recht lange Parameterlisten in den Reports und auch in den Set-Befehlen. Bisher ist das alles nicht sooo sicher geparst (wir hatten ja die Diskussion mit "Brot") und da müssten eigentlich auch einige bestehende Funktionen mal etwas erweitert werden.

Eine mögliche Lösung wäre die einzelnen komplexen Pattern in Variablen auszulagern:

  # hm2: hh:mm returns (hh) (mm)
  my $p_hm2 = "([01][0-9]|2[0-3]):([0-5][0-9])";

  # hms3: hh:mm:ss returns (hh) (mm) (ss)
  my $p_hms3 = "([01][0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9])";

  # b1: byte, 0-255 with and without leading zero, returns (number)
  my $p_b1 = "([01]?[0-9]?[0-9]|2[0-4][0-9]|25[0-5])";
 
  # wd1: weekday, returns (weekday)
  my $p_wd1 = "(mon|tue|wed|thu|fri|sat|sun)";
 
  if($arg !~
    #~ m/([01]) ([0-2]?[0-9]?[0-9]) ([0-2]?[0-9]?[0-9]) ([a-z]{3}) ([0-2]?[0-9]):([0-5]?[0-9]) ([0-2]?[0-9]):([0-5]?[0-9])/) {
    m/([01]) $p_b1 $p_b1 $p_wd1 $p_hm2 $p_hm2/) {
    return ("wrong format, see commandref", "");
  }

Diese Idee finde ich eigentlich gar nicht so schlecht, zum einen muss man sich dann nicht jedesmal das Pattern aus dem Kopf drücken, zum anderen wäre es eine Art Standard.
Außerdem  wäre anhand des namens schon mal etwas klarer was man da eigentlich parsen möchte. Für meinen kleinen Test habe ich an die pattern die Anzahl der Gruppen angehängt die im Pattern definiert sind und die dann ja als Variable zurückgegeben werden, damit hätte man auch einen Überblick wenn die Definition evtl. global am Anfang steht.
(Alternativ könnte man die Anzahl auch an das "p" anhängen, dann wäre man mit den "namen" der Pattern etwas freier)

Was hälst Du von soetwas?

Die andere Alternative wäre erstmal "grob" die Parameter zu parsen und in Variablen zu schreiben und die dann einzelnd zu parsen, das fände ich aber deutlich aufwändiger und auch unbübersichtlicher.

Gruß,
Andreas.

FB 7360, Homematic und ZWave
Support for ZWave-SECURITY

rudolfkoenig

Erstens sind Regel dazu da, um (in berechtigten Faellen) Ausnahmen zu erlauben, aber eine bessere Loesung mit Perl Variablen hast ja selbst gefunden. Eine weitere Alternative sind mehrzeilige Regexps mit dem x modifier, siehe http://www.perl.com/pub/2004/01/16/regexps.html oder "perldoc perlre", Abschnitt /x

A.Harrenberg

Hi Rudi,

auf den /x wäre ich nie gekommen... Man muss dann natürlich die Spaces explizit "richtig" angeben, was die Lesbarkeit dann wieder etwas verschlechtert, aber wenn man es wirklich so aufdröselt wie in dem Beispiel geht das auch.

Wärest Du denn einverstanden solche Pattern global (in ZWave_lib?) zu definieren?

Formatieren würde ich dann ggf. sogar in einer Kombination aus /x und den Variablen.

Gruß,
Andreas.
FB 7360, Homematic und ZWave
Support for ZWave-SECURITY

rudolfkoenig


A.Harrenberg

Hi Rudi,

dachte wenn es schon global definiert ist dann auch gleich für alle Module (00_ZWCul, 00_ZWDongle und 10_ZWave) und dann bietet sich ZWLib an das die ja von allen benutzt wird...
Ich werde dann mal ein paar Definitionen die ich benötige dort anlegen.

Danke,
Andreas.
FB 7360, Homematic und ZWave
Support for ZWave-SECURITY

rudolfkoenig

Verstehe immer noch nicht, wozu man Regexp-Patterns fuer alle Module (ZWave/ZWDongle/ZWCUL) anlegen moechte.

A.Harrenberg

Hi,

ich kann die auch nur in 10_ZWave anlegen...

Gruß,
Andreas.
FB 7360, Homematic und ZWave
Support for ZWave-SECURITY