Funktion für RegEx Escape?

Begonnen von DeeSPe, 25 März 2021, 10:52:12

Vorheriges Thema - Nächstes Thema

DeeSPe

Hallo liebe Programmierer,

gibt es in FHEM bereits eine Funktion um vorgegebene Strings zu escapen dass sie RegEx konform sind, ähnlich zu SemicolonEscape?
Meine Aufgabenstellung lautet ein Array mit Kalender-Events zu befüllen, aber keine doppelten Einträge zu haben. Dazu vergleiche ich per RegEx ob es den Eintrag im Array schon gibt:
push @events,$evt if (!grep /^$evt$/,@events);
Das Problem was sich nun hier gezeigt hat ist, dass im Kalender auch Sonderzeichen wie "?" stehen können und diese in RegEx eine bestimmte Bedeutung haben. Somit kommt es an der Stelle zum Crash.

Wenn es noch keine solche Funktion in FHEM gibt, macht es Sinn eine solche zu integrieren? Oder gibt es andere Möglichkeiten das zu umgehen? Wie handhabt ihr soetwas wenn man den vorgegebenen String selbst nicht unter Kontrolle hat?

Danke.

Gruß
Dan
MAINTAINER: 22_HOMEMODE, 98_Hyperion, 98_FileLogConvert, 98_serviced

Als kleine Unterstützung für meine Programmierungen könnt ihr mir gerne einen Kaffee spendieren: https://buymeacoff.ee/DeeSPe

rudolfkoenig

CheckRegexp($regexp, $context) prueft, ob ein Regexp zum Perl-Absturz fuehrt.

Eine Funktion, nachdem Du fragst, kenne ich nicht.
Wenn ich etwas nicht als Regexp pruefen will, dann pruefe ich es mit eq/ne.
Vermutlich denke ich aber zu einfach.

DeeSPe

Danke Rudi!
Die Funktion war mir bisher nicht aufgefallen.
Allerdings bringt sie mich in diesem Falle auch nicht wirklich weiter.

Wie könnte man denn mit "eg", statt meiner Version oben, das hinzuzufügende Element vorher prüfen ob es das selbe schon im Array gibt?
Kann mir da jemand bitte mal einen Denkanstoß geben?

Gruß
Dan
MAINTAINER: 22_HOMEMODE, 98_Hyperion, 98_FileLogConvert, 98_serviced

Als kleine Unterstützung für meine Programmierungen könnt ihr mir gerne einen Kaffee spendieren: https://buymeacoff.ee/DeeSPe

Beta-User

Weiß nicht, ob das weiterhilft, aber m.E. ist das hier in die Richtung "eq/ne", die Rudi angedeutet hat - die Array-Elemente werden dabei einfach als Label für einen Hash verwendet:

sub get_unique {
    my $arr    = shift;
    my $sorted = shift; #true if shall be sorted (longest first!)
   
    my %seen;
   
    #method 2 from https://stackoverflow.com/a/43873983
    my @unique = grep {!$seen{$_}++} @{$arr}; #we may need to sort, see https://stackoverflow.com/a/30448251
   
    return if !@unique;

    return @unique if !$sorted;

    my @sorted = sort { length($b) <=> length($a) } @unique;
    #Log3(undef, 5, "get_unique sorted to ".join q{ }, @sorted);
    return @sorted;
}


Übergeben wird die Referenz auf ein Array, sowie (optional) die Info, ob der Länge nach sortiert werden soll (längster string zuerst), z.B. so wie hier:
sub RHASSPY_allRhasspyNames {
    my $hash = shift // return;

    my @devices;

    return if !defined $hash->{helper}{devicemap};
    my $rRooms = $hash->{helper}{devicemap}{rhasspyRooms};
    for my $key (keys %{$rRooms}) {
        push @devices, keys %{$rRooms->{$key}};
    }
    return get_unique(\@devices, 1 );
}

(Stammt aus dem aktuellen Code von RHASSPY).
Server: HP-elitedesk@Debian 12, aktuelles FHEM@ConfigDB | CUL_HM (VCCU) | MQTT2: MiLight@ESP-GW, BT@OpenMQTTGw | MySensors: seriell, v.a. 2.3.1@RS485 | ZWave | ZigBee@deCONZ | SIGNALduino | MapleCUN | RHASSPY
svn: u.a MySensors, Weekday-&RandomTimer, Twilight,  div. attrTemplate-files

rudolfkoenig

push @events,$evt if (!grep { $_ eq $evt  },@events);

(ungetestet)

CoolTux

Zitat von: rudolfkoenig am 26 März 2021, 15:18:30
push @events,$evt if (!grep { $_ eq $evt  },@events);

(ungetestet)

Ich bilde mir ein das es ohne Komma vor @events sein muss

push @events,$evt if (!grep { $_ eq $evt  } @events);


leider ebenfalls ungetestet.


Grüße
Du musst nicht wissen wie es geht! Du musst nur wissen wo es steht, wie es geht.
Support me to buy new test hardware for development: https://www.paypal.com/paypalme/MOldenburg
My FHEM Git: https://git.cooltux.net/FHEM/
Das TuxNet Wiki:
https://www.cooltux.net

DeeSPe

Vielen Dank für Eure geteilten Lösungsansätze.
Ich komme leider erst nächste Woche dazu die Codeschnipsel zu testen, werde aber definitiv berichten ob ich damit Erfolg erziele.

Gruß
Dan
MAINTAINER: 22_HOMEMODE, 98_Hyperion, 98_FileLogConvert, 98_serviced

Als kleine Unterstützung für meine Programmierungen könnt ihr mir gerne einen Kaffee spendieren: https://buymeacoff.ee/DeeSPe

Christoph Morrison

https://perldoc.perl.org/List::Util#uniq (List::Util ist ein Core-Module und immer bei Perl dabei)

DeeSPe

Ist ja echt schon ewig her dass ich hier eine Rückmeldung geben wollte.
Habe heute erst einmal testweise den Vorschlag von Rudi/Marko umgesetzt. Das hat soweit ich es beurteilen kann gut geklappt.

Dann habe ich auch den Vorschlag von Christoph umgesetzt und muss sagen dass mit dieser noch besser gefällt.
Habe jetzt jedes grep rausgeworfen bei dem ich das Vorhandensein eines Elements im Array geprüft habe und dann nur vor Weitergabe des Array dieses mittel 'uniq' verschlankt.
Ich denke diese Lösung dürfte etwas performanter sein als im Loop immer wieder mit grep zu prüfen ob das Element schon vorhanden ist.

Danke nochmal an alle Beteiligten, auch wenn es lange gedauert hat bis ich das umgesetzt habe.

Gruß
Dan
MAINTAINER: 22_HOMEMODE, 98_Hyperion, 98_FileLogConvert, 98_serviced

Als kleine Unterstützung für meine Programmierungen könnt ihr mir gerne einen Kaffee spendieren: https://buymeacoff.ee/DeeSPe