[gelöst] Perl Klammern, Semikolon, Anführunsgzeichen und Punkte

Begonnen von Kohle77, 16 Juni 2021, 07:57:04

Vorheriges Thema - Nächstes Thema

Kohle77

Hallo,
ich weiß das Thema war schon hundertmal im Forum aber ich blick es einfach nicht.
Dieser artikel hilft mir auch nicht wirklich:
Zitathttps://wiki.fhem.de/wiki/Klammerebenen
oder dieser:
Zitathttps://wiki.fhem.de/wiki/Escapen_in_Perlbefehlen

*00:01 {my $Stand = ( if (".strftime "%W",localtime) ne ReadingsVal("ZSWoechentlich","oldKW",0)) {
my $Stand = ReadingsVal("Zaehlerstand","Akt_Ver",0);;
fhem("setreading ZSWoechentlich ".strftime("%W",localtime)." $Stand";;
fhem("setreading ZSWoechentlich oldKW ".strftime("%W",localtime)) )}


Ich würde mich riesig freuen wenn mir jemand sage könnte was in dem code falsch ist und wie es richtig heißen sollte.

Was ich im DEF editor sehe ich das ich keine schließende Klammer für
Zitat{my $Stand = ...
habe aber selbst wenn ich am ende noch eine } einfüge passt es nicht.

Danke
Christian

Beta-User

Na ja, wenn codemirror "motzt", dass die Klammern nicht passen, muss man sie ergänzen und den Fehler tendenziell woanders suchen (hier: Im Code, vermutlich wegen der Quotes)... Würde empfehlen, immer mit einem leeren Code anzufangen, wenn du Perl brauchst. Leerer Code = öffnende und schließende Klammer:
defmod t_at at *00:01 {}Dann machst du einfach danach dann in DEF ein paar Leerzeilen rein.

Mein ungetestetes Ergebnis sieht so aus:
{
my $wk = strftime '%W',localtime;
return if $wk eq ReadingsVal('ZSWoechentlich','oldKW',-1);
my $Stand = ReadingsVal('Zaehlerstand','Akt_Ver',0);
fhem("setreading ZSWoechentlich $wk $Stand";
return fhem("setreading ZSWoechentlich oldKW $wk");
}

Erläuterungen:
- Werte, die man häufiger braucht, darf man in Variablen packen. Das ist leserlicher, und beim extrapolieren passieren weniger Fehler (deine Quotes waren auch irgendwie "wild" verteilt)
- Wenn alles innerhalb der if-Abfrage stattfindet, kann man das auch so lösen, dass man den Code direkt beendet, wenn nichts passieren soll (return if ...)
- Default-Werte sollte man so wählen, dass die jeweilige Bedingung dazu paßt; hier also: darf nie passen => -1
- "Quotes in Perl": Was nicht extrapoliert werden muss, darf man auch in einfache Quotes packen.
- Zu guter Letzt: Explizite Rückgabeanweisungen sind zumeist auch kein Fehler... (das return könnte man hier auch in eine extra Zeile schreiben).
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

betateilchen

Zitat von: Beta-User am 16 Juni 2021, 09:48:27
Erläuterungen:
- "Quotes in Perl": Was nicht extrapoliert werden muss, darf man auch in einfache Quotes packen.

Genau. strftime() extrapoliert aber die Platzhalter. Deshalb sollte es besser

strftime "%W",localtime;

heißen.

Zitat von: Beta-User am 16 Juni 2021, 09:48:27
- Zu guter Letzt: Explizite Rückgabeanweisungen sind zumeist auch kein Fehler

Sind aber in diesem Fall nicht sinnvoll, da der Rückgabewert von fhem() überhaupt nicht benötigt wird.
Außerdem wird im Beispiel die Lesbarkeit erschwert.
-----------------------
Formuliere die Aufgabe möglichst einfach und
setze die Lösung richtig um - dann wird es auch funktionieren.
-----------------------
Lesen gefährdet die Unwissenheit!

Beta-User

Zitat von: betateilchen am 16 Juni 2021, 10:33:46
Genau. strftime() extrapoliert aber die Platzhalter. Deshalb sollte es besser

strftime "%W",localtime;

heißen.
...es wird allerdings mAn. erst nach der Übergabe der Parameter extrapoliert, nicht vorher. Jedenfalls bringt mir
{strftime '%W',localtime}das korrekte Ergebnis in FHEMWEB.
Zitat
Sind aber in diesem Fall nicht sinnvoll, da der Rückgabewert von fhem() überhaupt nicht benötigt wird.
Außerdem wird im Beispiel die Lesbarkeit erschwert.
Das mit der Lesbarkeit mag stimmen, aber unabhängig davon, ob das explizite return davor steht, liefert der Perl-Code zurück, was der fhem()-Aufruf zurückgibt. Nur wird wohl im Fall des Aufrufs aus at heraus so oder so alles nicht weiter verwendet, oder?

(Dieses implizite return-Verhalten ist mAn. was, das viele User gerade deswegen übersehen, weil es in praktisch allen Fällen, die via FHEMWEB einzugeben sind entweder nicht relevant oder (unausgesprochen) erwünscht ist (stateFormat, z.B.).
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

betateilchen

Zitat von: Beta-User am 16 Juni 2021, 10:53:07
...es wird allerdings mAn. erst nach der Übergabe der Parameter extrapoliert, nicht vorher.
Jedenfalls bringt mir ... das korrekte Ergebnis in FHEMWEB

Völlig richtig. Genau deshalb hatte ich auch "sollte es besser..." und nicht "sollte es richtig..." geschrieben.

Es ist einfach eine hilfreiche Gewohnheit, an den doppelten Anführungszeichen erkennen zu können,
dass sich ein Wert verändern wird/könnte und '%W' deshalb nirgends als Literal im Ergebnis auftauchen wird.
-----------------------
Formuliere die Aufgabe möglichst einfach und
setze die Lösung richtig um - dann wird es auch funktionieren.
-----------------------
Lesen gefährdet die Unwissenheit!

Christoph Morrison

Du solltest statt %W auch lieber %V nehmen, sonst wunderst du dich vielleicht am Jahrensende/-anfang.

https://metacpan.org/pod/POSIX::strftime::GNU

%W
The week number of the current year as a decimal number, range 00 to 53, starting with the first Monday as the first day of week 01.

vs.

%G, %g, and %V yield values calculated from the week-based year defined by the ISO 8601 standard. In this system, weeks start on a Monday, and are numbered from 01, for the first week, up to 52 or 53, for the last week. Week 1 is the first week where four or more days fall within the new year (or, synonymously, week 01 is: the first week of the year that contains a Thursday; or, the week that has 4 January in it). When three of fewer days of the first calendar week of the new year fall within that year, then the ISO 8601 week-based system counts those days as part of week 53 of the preceding year. For example, 1 January 2010 is a Friday, meaning that just three days of that calendar week fall in 2010. Thus, the ISO 8601 week- based system considers these days to be part of week 53 (%V) of the year 2009 (%G) ; week 01 of ISO 8601 year 2010 starts on Monday, 4 January 2010.

rabehd

fhem("setreading ZSWoechentlich ".strftime("%W",localtime)." $Stand";;
müßte doch
fhem("setreading ZSWoechentlich ".strftime("%W",localtime)." $Stand");;
sein. Zusammen mit deinem } müßte der Syntax stimmen.
Auch funktionierende Lösungen kann man hinterfragen.

Kohle77

Hi,
puh erstmal danke für die vielen Erklärungen. Hab leider wenig Zeit im moment werde mich aber wenn ich mehr Zeit habe mal genau damit beschäftigen. Wollte einfach nur kurz Rückmeldung geben das ich das nicht vergessen habe.

Vielen, vielen Dank erstmal.

Gruß
Christian

micky0867

*00:01 {my $Stand = ( if (".strftime "%W",localtime) ...

Ohne zu verstehen, was da passieren soll, sehe ich 3 Anführungszeichen.
Kann das erste ein Tippfehler sein?

Kohle77

Hallo,
danke für eure Hilfe. Eine schließende Klammer hat gefehlt am Ende von $wk $Stand aber so funktioniert es.

*00:01 {
my $wk = strftime '%V',localtime;;
return if $wk eq ReadingsVal('ZSWoechentlich','oldKW',-1);;
my $Stand = ReadingsVal('Zaehlerstand','Akt_Ver',0);;
fhem("setreading ZSWoechentlich $wk $Stand");;
return fhem("setreading ZSWoechentlich oldKW $wk");;
}


Nochmals danke
Christian