[gelöst] Regex Frage mit multiple matches

Begonnen von Sirel, 15 Februar 2021, 20:18:34

Vorheriges Thema - Nächstes Thema

Sirel

Hallo zusammen,
ich nutze das Calender Modul und habe dort meinen Müllkalender hinterlegt.
Jetzt würde ich gerne, ohne weiteres Hilfsmodul wie CalView etc., die Termine auslesen und sofern eine Mülltonne abgeholt wird, mir diese Info zukommen lassen.
Ich habe mir das in eine myutils gepackt.


my $events= fhem ('get muellabfuhr_ical events format:custom="$S" limit:from=+1d,limit:to=+10d');

if ($events =~ /(\S+(?=tonne))/g)
{return $1};


Die Variable $1 ist mit dem ersten Treffer aus der Response vom Calender befüllt - in diesem Fall mit "Restmüll".

Die Response vom Calender ist aber umfangreicher


RSAG Restmülltonne 2-wö.
RSAG Biotonne 2-wö.
RSAG Biotonne Regelabfuhr


Ich hätte verstanden, dass jeder "Match" der Expression in eine separate Variable geschrieben wird ($1, $2,...,$n). Alle weiteren Variabeln sind in meinem Fall aber leer.

Wird das Global-Flag /g nicht berücksichtigt, oder funktionieren die Variablen nur ohne das Global Flag?

Mit anderen Worten: Wie bekomme ich es hin, dass in Variable 1 Restmüll, in Variable 2 Biotonne und in Variable 3 ebenfalls Biotonne steht?

Besten Dank vorab und Grüße,

Max


DeeSPe

Mach mal das draus, dann sollte Deine Variablenzuweisung $1, $2, $3 klappen:
if ($events =~ /((?:\S+tonne)+)/g)

Hier auch eine Beschreibung dazu: https://www.regular-expressions.info/captureall.html

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

DeeSPe

Ich glaube das ist immer noch nicht ganz richtig.
Ich gucke nochmal wie man das lösen kann.

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

Otto123

Hi,

ich bin mir mit Dan seiner Antwort nicht sicher. Es sind auch wieder einzelne Groupmatches ?
Ich habe etwas rumprobiert komme aber auch nicht auf die Lösung.
Aber zu Deiner Frage ein Beispiel für die Raw Def zum reinwerfen (keine Lösung)
{my $events="RSAG Restmülltonne 2-wö.\
RSAG Biotonne 2-wö.\
RSAG Biotonne Regelabfuhr";;\
$events =~ /(Biotonne).*\n.*(Regel)/g;;\
return $2}

Wie Du siehst die erste Klammer kommt nach $1 und die zweite Klammer kommt nach $2. 

Kannst Du Dir hier anschauen https://regex101.com/r/YbTIuF/1

Wenn ich es richtig verstehe braucht man ein Fullmatch über 3 Zeilen und darin 3 Groupmatches.

Gruß Otto
Viele Grüße aus Leipzig  ⇉  nächster Stammtisch an der Lindennaundorfer Mühle
RaspberryPi B B+ B2 B3 B3+ ZeroW,HMLAN,HMUART,Homematic,Fritz!Box 7590,WRT3200ACS-OpenWrt,Sonos,VU+,Arduino nano,ESP8266,MQTT,Zigbee,deconz

Otto123

#4
Aus Verzweiflung: ;D
$events =~ /((?:\S+tonne)+).*\nRSAG.((?:\S+tonne)+).*\nRSAG.((?:\S+tonne)+)/g
So geht es - aber nicht schön?
Viele Grüße aus Leipzig  ⇉  nächster Stammtisch an der Lindennaundorfer Mühle
RaspberryPi B B+ B2 B3 B3+ ZeroW,HMLAN,HMUART,Homematic,Fritz!Box 7590,WRT3200ACS-OpenWrt,Sonos,VU+,Arduino nano,ESP8266,MQTT,Zigbee,deconz

Christoph Morrison

Zitat
Jetzt würde ich gerne, ohne weiteres Hilfsmodul wie CalView etc., die Termine auslesen und sofern eine Mülltonne abgeholt wird, mir diese Info zukommen lassen.
Warum tust du dir da so schwer mit selbst die Termine rauszupopeln, wenn du das ABFALL-Modul dafür nutzen kannst?

DeeSPe

Zitat von: Otto123 am 15 Februar 2021, 22:10:52
Aus Verzweiflung: ;D
$events =~ /((?:\S+tonne)+).*\nRSAG.((?:\S+tonne)+).*\nRSAG.((?:\S+tonne)+)/g
So geht es - aber nicht schön?

So ähnlich habe ich es auch gerade gemacht:
$events =~ /\S+.(\S+tonne).\S+\n\S+.(\S+tonne).\S+\n\S+.(\S+tonne)/
Dann sind die Variablen $1, $2, $3 befüllt.

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

Otto123

#7
Zitat von: Christoph Morrison am 15 Februar 2021, 22:19:31
Warum tust du dir da so schwer mit selbst die Termine rauszupopeln, wenn du das ABFALL-Modul dafür nutzen kannst?
Ich bin Abfallmodulgeschädigter und kann Sirel nur zu dieser Vorgehensweise beglückwünschen.  ;D
Keine unnötige Abhängigkeit von zusätzlichen Modulen und Entwicklern. Vor allem nicht wegen einer Mülltonne. Calendar macht das mit einem userReadings :)

@Dan 👍 - ich habe es wegen der Erklärung mal noch gespeichert https://regex101.com/r/khOQ4I/1 ;)
Viele Grüße aus Leipzig  ⇉  nächster Stammtisch an der Lindennaundorfer Mühle
RaspberryPi B B+ B2 B3 B3+ ZeroW,HMLAN,HMUART,Homematic,Fritz!Box 7590,WRT3200ACS-OpenWrt,Sonos,VU+,Arduino nano,ESP8266,MQTT,Zigbee,deconz

Sirel

Zitat von: DeeSPe am 15 Februar 2021, 22:20:09
So ähnlich habe ich es auch gerade gemacht:
$events =~ /\S+.(\S+tonne).\S+\n\S+.(\S+tonne).\S+\n\S+.(\S+tonne)/
Dann sind die Variablen $1, $2, $3 befüllt.

Gruß
Dan

Hi Dan,

ich glaube, das ist der einzig gangbare Weg. Habe mir vorhin noch mal die Stelle durchgelesen, über welche ich auf die Variablen gekommen bin.
Dort heißt es:

Es gibt noch einen Nebeneffekt: Perl speichert die gefunden Ergebnisse beim Mustervergleich ab und zwar in die Variablen: $1 für die erste Klammerung, $2 für die zweite Klammerung, etc. Es zählt dabei die linke Klammer

Quelle:
http://www.mathe2.uni-bayreuth.de/perl/GK/regExp.htm#klammerung

Wie von dir ergänzt, werden durch die zusätzlichen Abfragen in Klammern die weiteren Variablen befüllt.
Unschön ist, dass es quasi ,,Hard Coded" ist, denn sobald mehr Ereignisse stattfinden als ,,Klammern" gesetzt sind, bekommt man davon nichts mit.

Vielleicht hilft es auch, das Ergebnis von Calender nicht als Text, sondern als Array auszugeben. Das lässt sich dann besser auswerten.

Dazu dann mehr morgen...

Viele Grüße,
Max

DeeSPe

#9
Das wäre sonst auch mein nächster Vorschlag gewesen.
Einfach am Zeilenumbruch splitten und dann den RegEx drauf.
my @tonnen = map {$1 if $_=~/\S+.(\S+tonne)/} split("\n",$events);
Jetzt hast Du im Array @tonnen alle Tonnennamen, egal wie viele.
Vielleicht hilft Dir das ja weiter.

Gruß
Dan

EDIT: Oder falls Du gleich ein Array statt $events verarbeiten willst eben:
my @tonnen = map {$1 if $_=~/\S+.(\S+tonne)/} @events;
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

Sirel

Hallo zusammen,

ich muss noch mal nachhaken.

Ich habe das Gefühl, dass das Array über die Kalenderfunktion nicht richtig befüllt wird.

Wenn ich das Array über diesen Befehl anlege und befülle

@events = fhem ('get muellabfuhr_ical events format:custom="$S" limit:from=+0d,limit:to=+10d returnType:@texts');

sollte ich doch per

$tonne = @array[0]

in der Variablen $tonne sehen, welcher Eintrag im Array an Position 0 ist.

Da wird mir aber gar kein Eintrag angezeigt. Ich habe das Gefühl, dass die Calenderfunktion nicht richtig funktioniert.
Entsprechend funktioniert es auch nicht, anschließend die RegEx-Matches in ein weiteres Array zu schreiben.

Kann das jemand probieren zu reproduzieren?

Vielen Dank und Grüße,

Max

Otto123

#11
Hallo Max,

ich kann es teils nachvollziehen. Ich bekomme immer nur eine Zahl 2 für 2 Events zurück.
Was funktioniert ist dies:
{my @events=split "\n",(fhem('get AbfallKalender events format:custom="$S" limit:from=+0d,limit:to=+10d returnType:$text'));;$events[0]}

Allerdings habe ich im Termin selbst immer nur einen Eintrag und bekomme mit dieser Abfrage zwei getrennte Termine in ein Array.

Gruß Otto
Viele Grüße aus Leipzig  ⇉  nächster Stammtisch an der Lindennaundorfer Mühle
RaspberryPi B B+ B2 B3 B3+ ZeroW,HMLAN,HMUART,Homematic,Fritz!Box 7590,WRT3200ACS-OpenWrt,Sonos,VU+,Arduino nano,ESP8266,MQTT,Zigbee,deconz

DeeSPe

Zitat von: Sirel am 17 Februar 2021, 23:05:07
Hallo zusammen,

ich muss noch mal nachhaken.

Ich habe das Gefühl, dass das Array über die Kalenderfunktion nicht richtig befüllt wird.

Wenn ich das Array über diesen Befehl anlege und befülle

@events = fhem ('get muellabfuhr_ical events format:custom="$S" limit:from=+0d,limit:to=+10d returnType:@texts');

sollte ich doch per

$tonne = @array[0]

in der Variablen $tonne sehen, welcher Eintrag im Array an Position 0 ist.

Da wird mir aber gar kein Eintrag angezeigt. Ich habe das Gefühl, dass die Calenderfunktion nicht richtig funktioniert.
Entsprechend funktioniert es auch nicht, anschließend die RegEx-Matches in ein weiteres Array zu schreiben.

Kann das jemand probieren zu reproduzieren?

Vielen Dank und Grüße,

Max

Bei mir kommt auch nur die Zahl der enthaltenen Einträge an.

Aber wie vorher schon geschrieben einfach am Zeilenumbruch aufteilen und dann weiter verarbeiten.

  my @e = split("\n",fhem 'get muellabfuhr_ical events format:custom="$S" limit:from=+1d,limit:to=+10d');
  my @t;
  for (@e) {
    push @t,$1 if $_=~/\S+.(\S+tonne)/;
  }
  return join(",",@t);

Damit hast Du in @t alle Tonnen. Ein for Loop ist hier besser als map da es evtl. sonst leere Einträge im Array gibt.

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

hydrotec

Hallo Max,

Zitat von: Sirel am 15 Februar 2021, 20:18:34
..., die Termine auslesen und sofern eine Mülltonne abgeholt wird, mir diese Info zukommen lassen.
Ich habe mir das in eine myutils gepackt.

Eventuell hilft dir https://forum.fhem.de/index.php/topic,114901.msg1092847.html#msg1092847 weiter.

Gruß Karsten

Otto123

Hallo Max,

Ich hatte vielleicht die Aufgabe missverstanden: Sind jetzt in einem Termineintrag mehrere Tonnen in Zeilen hinterlegt - oder liefert die Abfrage mehrere Termine in Zeilen.
Bei ersterem könnte das Calendar Modul ja eh  nicht viel machen, da musst Du selbst ran.

Ich frage einfach nur den nächsten Termin und damit die nächste Tonne ab. Allerdings gibt es bei mir nicht mehrere Tonnen am Tag.
limit:from=0,count=1

Gruß Otto
Viele Grüße aus Leipzig  ⇉  nächster Stammtisch an der Lindennaundorfer Mühle
RaspberryPi B B+ B2 B3 B3+ ZeroW,HMLAN,HMUART,Homematic,Fritz!Box 7590,WRT3200ACS-OpenWrt,Sonos,VU+,Arduino nano,ESP8266,MQTT,Zigbee,deconz