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
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
Ich glaube das ist immer noch nicht ganz richtig.
Ich gucke nochmal wie man das lösen kann.
Gruß
Dan
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
Aus Verzweiflung: ;D
$events =~ /((?:\S+tonne)+).*\nRSAG.((?:\S+tonne)+).*\nRSAG.((?:\S+tonne)+)/g
So geht es - aber nicht schön?
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 (https://wiki.fhem.de/wiki/ABFALL)-Modul dafür nutzen kannst?
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
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 (https://wiki.fhem.de/wiki/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 ;)
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 (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
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;
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
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
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
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 (https://forum.fhem.de/index.php/topic,114901.msg1092847.html#msg1092847) weiter.
Gruß Karsten
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
Hallo zusammen,
ich habe es nun wie folgt gelöst. Schön schlank und performant m. E. n.
Ein DOIF triggert die Routine, sofern am Folgetag ein Event ansteht:
([20:00] and defined fhem ('get muellabfuhr_ical events format:custom="$S" limit:when=tomorrow')) ({Muellabfuhr}) DOELSE
Die Rutine ist wie folgt:
sub Muellabfuhr() {
# Holt die entsprechenden Kalendereinträge. Am Zeilenumbruch der Response wird getrennt und in das Array geschrieben.
my @e = split("\n",fhem 'get muellabfuhr_ical events format:custom="$S" limit:when=tomorrow');
my @t;
# das Array aus dem Kalender wird durchlaufen. Der Teil des Wortes, auf welches die Regex matched, befindet sich dann in der Variablen $1 und wird dann in das Array gepushed wird.
for (@e) {
push @t,$1 if $_=~/\S+.(\S+tonne)/;
}
# Da Doubletten auftreten können, werden sie rausgefiltert. Dazu wird eine Hash Variable wird angelegt. Jedem Wert aus dem Array t wird als Pair der Wert 1 zugeordnet. Der Wert ist völlig ega.
# Am Ende werden die Hashes in das Array tonnen geschrieben
my %all= ();
@all{@t}= 1;
my @tonnen_1 = (keys %all);
# Das Array wird über ein join in einen Variable gejoined. Dabei werden Zeileneinbrüche eingefügt.
my $tonne = join("\n",@tonnen_1);
#Versand per Telegram
{fhem ("set xxxx send Morgen müssen folgende Tonnen rausgestellt werden \\n$tonne")};
}
1;
Finde die Lösung für mich optimal, vielleicht hilft sie anderen ebenfalls.
Besten Dank an @DeeSPe und @Otto123 für die Hilfe und den wertvollen Input.
Max
Mach doch gleich so, dann sind erst gar keine Dubletten im Array:
for (@e) {
push @t,$1 if $_=~/\S+.(\S+tonne)/ && !grep(/^$1$/,@t);
}
Schön dass Du nun eine Lösung für Dich hast.
Gruß
Dan