Autor Thema: mal wieder split Verwirrung  (Gelesen 464 mal)

Online DeeSPe

  • Developer
  • Hero Member
  • ****
  • Beiträge: 3400
  • Wer anderen eine Bratwurst brät...
mal wieder split Verwirrung
« am: 19 März 2017, 16:30:53 »
Ich ärgere mich gerade mal wieder mit split rum.
Eigentlich benutzte ich split bisher so um einen String an den Leerzeichen zu trennen:
split(" ",$string)
Das klappte so bisher auch immer.

Beim Studieren noch split wird aber statt " immer / verwendet.
Da ich auch statt einen einfachen " " (Space) alle Arten von Whitespace abdecken wollte habe ich mal meine split(s) umgeschrieben in:
split(/\s+/,$string)
\s+ sollte laut RegEx also jede Form eines Whitespace abdecken (\r,\n,\t).

Leider scheint das aber so nicht ganz zu klappen, denn selbst das Ergebnis von split(" ",$string) und split(/ /,$string) unterscheidet sich.

Mein konkretes Problem:
Ich mache Energieberechnungen.
Das klappt:
  my $power;
  my $energy;
  foreach (devspec2array("$hash->{SENSORSENERGY}:FILTER=energy=.*:FILTER=power=.*"))
  {
    $power += (split(" ",ReadingsVal($_,"power",0)))[0];
    $energy += (split(" ",ReadingsVal($_,"energy",0)))[0];
  }

Das klappt aber nicht:
  my $power;
  my $energy;
  foreach (devspec2array("$hash->{SENSORSENERGY}:FILTER=energy=.*:FILTER=power=.*"))
  {
    $power += (split(/\s+/,ReadingsVal($_,"power",0)))[0];
    $energy += (split(/\s+/,ReadingsVal($_,"energy",0)))[0];
  }

Ich grübel schon eine Weile drüber, komme aber nicht auf den Fehler.
Kann mich jemand erleuchten?

Gruß
Dan
FHEM 5.8, Brix, VIVO mini, RPi3, Debian Jessie, ZME_UZB1
HM-CFG-LAN, HM-MOD-UART-WIFI, HUE, HarmonyHub, JeeLink, CO20
Hyperion auf RPi Zero W, Sonos, viel Z-Wave und HM
alles per HomeKit steuerbar
MAINTAINER: 22_HOMEMODE, 98_Hyperion, 98_FileLogConvert

Online zap

  • Developer
  • Hero Member
  • ****
  • Beiträge: 1650
    • HMCCU
Antw:mal wieder split Verwirrung
« Antwort #1 am: 19 März 2017, 16:34:22 »
Ein " " trennt bein einzelnen Leerzeichen. Ein \s auch, ein \s+ hingegen bei 1 oder mehreren aufeinanderfolgenden
CCU2 mit diversen Komponenten (Fenster, Rolladen, Themostate, Stromzähler, Steckdosen ...)
FHEM mit Raspi für den Rest (Sonos, AVR, Meteohub, Beacons, Heizung, Hue)
HMCCU: Schnittstelle CCU2 - FHEM (best of both worlds approach)

Online DeeSPe

  • Developer
  • Hero Member
  • ****
  • Beiträge: 3400
  • Wer anderen eine Bratwurst brät...
Antw:mal wieder split Verwirrung
« Antwort #2 am: 19 März 2017, 16:35:58 »
Ein " " trennt bein einzelnen Leerzeichen. Ein \s auch, ein \s+ hingegen bei 1 oder mehreren aufeinanderfolgenden

Ja, genau das ist ja mein Zweck. Man weiß ja nie wie viele Leerzeichen in so einem Reading stecken können und somit will ich jede Form abdecken.
Hauptproblem ist halt schon der Unterschied zwischen " " und / /.

Gruß
Dan
FHEM 5.8, Brix, VIVO mini, RPi3, Debian Jessie, ZME_UZB1
HM-CFG-LAN, HM-MOD-UART-WIFI, HUE, HarmonyHub, JeeLink, CO20
Hyperion auf RPi Zero W, Sonos, viel Z-Wave und HM
alles per HomeKit steuerbar
MAINTAINER: 22_HOMEMODE, 98_Hyperion, 98_FileLogConvert

Online DeeSPe

  • Developer
  • Hero Member
  • ****
  • Beiträge: 3400
  • Wer anderen eine Bratwurst brät...
Antw:mal wieder split Verwirrung
« Antwort #3 am: 19 März 2017, 17:06:10 »
Hab  mal weiter analysiert!

  foreach (devspec2array("$hash->{SENSORSENERGY}:FILTER=energy=.*:FILTER=power=.*"))
  {
    my $po = join(":",split(" ",ReadingsVal($_,"power",0)));
    my $eo = join(":",split(" ",ReadingsVal($_,"energy",0)));
    my $pn = join(":",split(/\s+/,ReadingsVal($_,"power",0)));
    my $en = join(":",split(/\s+/,ReadingsVal($_,"energy",0)));
    Debug "eo: '$eo', po: '$po'";
    Debug "en: '$en', pn: '$pn'";
  }

Ergibt:
2017.03.19 17:01:25 1 : DEBUG>eo: '6.06:kWh', po: '4.4:W'
2017.03.19 17:01:25 1 : DEBUG>en: ':6.06:kWh', pn: '4.4:W'
2017.03.19 17:01:25 1 : DEBUG>eo: '9.45:kWh', po: '10.8:W'
2017.03.19 17:01:25 1 : DEBUG>en: ':9.45:kWh', pn: '10.8:W'
2017.03.19 17:01:25 1 : DEBUG>eo: '87.26:kWh', po: '157.5:W'
2017.03.19 17:01:25 1 : DEBUG>en: ':87.26:kWh', pn: '157.5:W'
2017.03.19 17:01:25 1 : DEBUG>eo: '15.67:kWh', po: '1.4:W'
2017.03.19 17:01:25 1 : DEBUG>en: ':15.67:kWh', pn: '1.4:W'
2017.03.19 17:01:25 1 : DEBUG>eo: '10.22:kWh', po: '1.6:W'
2017.03.19 17:01:25 1 : DEBUG>en: ':10.22:kWh', pn: '1.6:W'
2017.03.19 17:01:25 1 : DEBUG>eo: '2.35:kWh', po: '0.9:W'
2017.03.19 17:01:25 1 : DEBUG>en: ':2.35:kWh', pn: '0.9:W'
2017.03.19 17:01:25 1 : DEBUG>eo: '8.47:kWh', po: '14.6:W'
2017.03.19 17:01:25 1 : DEBUG>en: ':8.47:kWh', pn: '14.6:W'
2017.03.19 17:01:25 1 : DEBUG>eo: '6.32:kWh', po: '0.9:W'
2017.03.19 17:01:25 1 : DEBUG>en: ':6.32:kWh', pn: '0.9:W'
2017.03.19 17:01:25 1 : DEBUG>eo: '13.73:kWh', po: '5.9:W'
2017.03.19 17:01:25 1 : DEBUG>en: ':13.73:kWh', pn: '5.9:W'
2017.03.19 17:01:25 1 : DEBUG>eo: '7.05:kWh', po: '3.7:W'
2017.03.19 17:01:25 1 : DEBUG>en: ':7.05:kWh', pn: '3.7:W'
2017.03.19 17:01:25 1 : DEBUG>eo: '146.55:kWh', po: '86.9:W'
2017.03.19 17:01:25 1 : DEBUG>en: ':146.55:kWh', pn: '86.9:W'
2017.03.19 17:01:25 1 : DEBUG>eo: '13.49:kWh', po: '77.3:W'
2017.03.19 17:01:25 1 : DEBUG>en: ':13.49:kWh', pn: '77.3:W'
2017.03.19 17:01:25 1 : DEBUG>eo: '3.24:kWh', po: '1.8:W'
2017.03.19 17:01:25 1 : DEBUG>en: ':3.24:kWh', pn: '1.8:W'
2017.03.19 17:01:25 1 : DEBUG>eo: '6:kWh', po: '5.0:W'
2017.03.19 17:01:25 1 : DEBUG>en: ':6:kWh', pn: '5.0:W'
2017.03.19 17:01:25 1 : DEBUG>eo: '1.91:kWh', po: '0.9:W'
2017.03.19 17:01:25 1 : DEBUG>en: ':1.91:kWh', pn: '0.9:W'

Warum gibt es bei der Variante mit \s+ vor dem ersten Value noch ein leeres Value? Genau das sollte doch \s+ eigentlich abdecken wenn ich es richtig verstanden habe!?
Die Verwirrung steigert sich gerade noch mehr. ??? ??? ???

Gruß
Dan
FHEM 5.8, Brix, VIVO mini, RPi3, Debian Jessie, ZME_UZB1
HM-CFG-LAN, HM-MOD-UART-WIFI, HUE, HarmonyHub, JeeLink, CO20
Hyperion auf RPi Zero W, Sonos, viel Z-Wave und HM
alles per HomeKit steuerbar
MAINTAINER: 22_HOMEMODE, 98_Hyperion, 98_FileLogConvert

Online DeeSPe

  • Developer
  • Hero Member
  • ****
  • Beiträge: 3400
  • Wer anderen eine Bratwurst brät...
Antw:mal wieder split Verwirrung
« Antwort #4 am: 19 März 2017, 17:12:49 »
Die letzte Variante jetzt auch noch!
Auch ein leeres erstes Value:
  foreach (devspec2array("$hash->{SENSORSENERGY}:FILTER=energy=.*:FILTER=power=.*"))
  {
    my $po = join(":",split(" ",ReadingsVal($_,"power",0)));
    my $eo = join(":",split(" ",ReadingsVal($_,"energy",0)));
    my $pr = join(":",split(/ /,ReadingsVal($_,"power",0)));
    my $er = join(":",split(/ /,ReadingsVal($_,"energy",0)));
    my $pn = join(":",split(/\s+/,ReadingsVal($_,"power",0)));
    my $en = join(":",split(/\s+/,ReadingsVal($_,"energy",0)));
    Debug "eo: '$eo', po: '$po'";
    Debug "er: '$er', pr: '$pr'";
    Debug "en: '$en', pn: '$pn'";
  }

2017.03.19 17:09:49 1 : DEBUG>eo: '6.06:kWh', po: '4.4:W'
2017.03.19 17:09:49 1 : DEBUG>er: ':6.06:kWh', pr: '4.4:W'
2017.03.19 17:09:49 1 : DEBUG>en: ':6.06:kWh', pn: '4.4:W'
2017.03.19 17:09:49 1 : DEBUG>eo: '9.45:kWh', po: '4.8:W'
2017.03.19 17:09:49 1 : DEBUG>er: ':9.45:kWh', pr: '4.8:W'
2017.03.19 17:09:49 1 : DEBUG>en: ':9.45:kWh', pn: '4.8:W'
2017.03.19 17:09:49 1 : DEBUG>eo: '87.26:kWh', po: '157.5:W'
2017.03.19 17:09:49 1 : DEBUG>er: ':87.26:kWh', pr: '157.5:W'
2017.03.19 17:09:49 1 : DEBUG>en: ':87.26:kWh', pn: '157.5:W'
2017.03.19 17:09:49 1 : DEBUG>eo: '15.67:kWh', po: '1.4:W'
2017.03.19 17:09:49 1 : DEBUG>er: ':15.67:kWh', pr: '1.4:W'
2017.03.19 17:09:49 1 : DEBUG>en: ':15.67:kWh', pn: '1.4:W'
2017.03.19 17:09:49 1 : DEBUG>eo: '10.22:kWh', po: '1.6:W'
2017.03.19 17:09:49 1 : DEBUG>er: ':10.22:kWh', pr: '1.6:W'
2017.03.19 17:09:49 1 : DEBUG>en: ':10.22:kWh', pn: '1.6:W'
2017.03.19 17:09:49 1 : DEBUG>eo: '2.35:kWh', po: '0.9:W'
2017.03.19 17:09:49 1 : DEBUG>er: ':2.35:kWh', pr: '0.9:W'
2017.03.19 17:09:49 1 : DEBUG>en: ':2.35:kWh', pn: '0.9:W'
2017.03.19 17:09:49 1 : DEBUG>eo: '8.47:kWh', po: '14.6:W'
2017.03.19 17:09:49 1 : DEBUG>er: ':8.47:kWh', pr: '14.6:W'
2017.03.19 17:09:49 1 : DEBUG>en: ':8.47:kWh', pn: '14.6:W'
2017.03.19 17:09:49 1 : DEBUG>eo: '6.32:kWh', po: '0.9:W'
2017.03.19 17:09:49 1 : DEBUG>er: ':6.32:kWh', pr: '0.9:W'
2017.03.19 17:09:49 1 : DEBUG>en: ':6.32:kWh', pn: '0.9:W'
2017.03.19 17:09:49 1 : DEBUG>eo: '13.73:kWh', po: '4.9:W'
2017.03.19 17:09:49 1 : DEBUG>er: ':13.73:kWh', pr: '4.9:W'
2017.03.19 17:09:49 1 : DEBUG>en: ':13.73:kWh', pn: '4.9:W'
2017.03.19 17:09:49 1 : DEBUG>eo: '7.05:kWh', po: '3.8:W'
2017.03.19 17:09:49 1 : DEBUG>er: ':7.05:kWh', pr: '3.8:W'
2017.03.19 17:09:49 1 : DEBUG>en: ':7.05:kWh', pn: '3.8:W'
2017.03.19 17:09:49 1 : DEBUG>eo: '146.58:kWh', po: '86.5:W'
2017.03.19 17:09:49 1 : DEBUG>er: ':146.58:kWh', pr: '86.5:W'
2017.03.19 17:09:49 1 : DEBUG>en: ':146.58:kWh', pn: '86.5:W'
2017.03.19 17:09:49 1 : DEBUG>eo: '13.49:kWh', po: '78.0:W'
2017.03.19 17:09:49 1 : DEBUG>er: ':13.49:kWh', pr: '78.0:W'
2017.03.19 17:09:49 1 : DEBUG>en: ':13.49:kWh', pn: '78.0:W'
2017.03.19 17:09:49 1 : DEBUG>eo: '3.24:kWh', po: '1.8:W'
2017.03.19 17:09:49 1 : DEBUG>er: ':3.24:kWh', pr: '1.8:W'
2017.03.19 17:09:49 1 : DEBUG>en: ':3.24:kWh', pn: '1.8:W'
2017.03.19 17:09:49 1 : DEBUG>eo: '6:kWh', po: '5.0:W'
2017.03.19 17:09:49 1 : DEBUG>er: ':6:kWh', pr: '5.0:W'
2017.03.19 17:09:49 1 : DEBUG>en: ':6:kWh', pn: '5.0:W'
2017.03.19 17:09:49 1 : DEBUG>eo: '1.91:kWh', po: '0.9:W'
2017.03.19 17:09:49 1 : DEBUG>er: ':1.91:kWh', pr: '0.9:W'
2017.03.19 17:09:49 1 : DEBUG>en: ':1.91:kWh', pn: '0.9:W'

Wieso ist " " und / / unterschiedlich?
Ich möchte es nur verstehen, denn ich sehe eigentlich im Reading keinen Unterschied.

Gruß
Dan
FHEM 5.8, Brix, VIVO mini, RPi3, Debian Jessie, ZME_UZB1
HM-CFG-LAN, HM-MOD-UART-WIFI, HUE, HarmonyHub, JeeLink, CO20
Hyperion auf RPi Zero W, Sonos, viel Z-Wave und HM
alles per HomeKit steuerbar
MAINTAINER: 22_HOMEMODE, 98_Hyperion, 98_FileLogConvert

Offline Markus Bloch

  • Administrator
  • Hero Member
  • *****
  • Beiträge: 3226
Antw:mal wieder split Verwirrung
« Antwort #5 am: 19 März 2017, 21:01:39 »
Hallo Dan,

die Antwort dazu steht in der Perl-Doku zu split():

As another special case, split emulates the default behavior of the command line tool awk when the PATTERN is either omitted or a string composed of a single space character (such as ' ' or "\x20" , but not e.g. / / ). In this case, any leading whitespace in EXPR is removed before splitting occurs, and the PATTERN is instead treated as if it were /\s+/ ; in particular, this means that any contiguous whitespace (not just a single space character) is used as a separator. However, this special treatment can be avoided by specifying the pattern / / instead of the string " " , thereby allowing only a single space character to be a separator. In earlier Perls this special case was restricted to the use of a plain " " as the pattern argument to split; in Perl 5.18.0 and later this special case is triggered by any expression which evaluates to the simple string " " .

Ist ein Perl-Feature ;)

Gruß
Markus
« Letzte Änderung: 19 März 2017, 21:03:30 von Markus Bloch »
Developer für Module: YAMAHA_AVR, YAMAHA_BD, FB_CALLMONITOR, FB_CALLLIST, PRESENCE, Pushsafer, LGTV_IP12, version

aktives Mitglied des FHEM e.V. (Technik)

Online DeeSPe

  • Developer
  • Hero Member
  • ****
  • Beiträge: 3400
  • Wer anderen eine Bratwurst brät...
Antw:mal wieder split Verwirrung
« Antwort #6 am: 19 März 2017, 22:26:25 »
Ich habe auch diesen Teil gelesen.
Leider werde ich daraus nicht schlau weil ich nicht weiß was "default behavior of the command line tool awk" bedeutet.
Was ist "default behavior" von awk?
Ich denke dass ich halbwegs englisch verstehe, aber diese Erklärung gibt mir Rätsel auf.
Wie mache ich es nun richtig wenn ich an jeglicher Form von Whitespace (" ","        ","\t","\t\t\t","\r","\n") trennen will?
Was ist so falsch an /\s+/?

Gruß
Dan
FHEM 5.8, Brix, VIVO mini, RPi3, Debian Jessie, ZME_UZB1
HM-CFG-LAN, HM-MOD-UART-WIFI, HUE, HarmonyHub, JeeLink, CO20
Hyperion auf RPi Zero W, Sonos, viel Z-Wave und HM
alles per HomeKit steuerbar
MAINTAINER: 22_HOMEMODE, 98_Hyperion, 98_FileLogConvert

Offline Reinerlein

  • Developer
  • Hero Member
  • ****
  • Beiträge: 1779
Antw:mal wieder split Verwirrung
« Antwort #7 am: 20 März 2017, 14:19:40 »
Hi Dan,

in der Beschreibung steht doch wie awk arbeiten würde (bzw. wie das von Perl gesehen wird):
Es werden alle führenden Leerzeichen (genauer: Whitespaces) entfernt. Also ein vorderes Trim. Des Weiteren wird ein " " wie ein /\s+/ behandelt, trifft also auch beliebig viele Leerzeichen zwischen den wichtigen Teilstrings.

Ein " " verhält sich also wie /\s+/ zzgl. eines vorderen trim()...

Grüße
Reiner

Online DeeSPe

  • Developer
  • Hero Member
  • ****
  • Beiträge: 3400
  • Wer anderen eine Bratwurst brät...
Antw:mal wieder split Verwirrung
« Antwort #8 am: 20 März 2017, 15:03:01 »
Danke für die Erklärung Reiner.
Ich denke damit habe ich es besser verstanden.
" " ist also wirklich ein Spezialfall und damit wären die Ergebnisse der folgenden 3 Möglichkeiten gleich!?
split " ",$str
trim split /\s+/,$str
split /[ \t\r\n]+/,$str

Gruß
Dan
« Letzte Änderung: 20 März 2017, 15:15:00 von DeeSPe »
FHEM 5.8, Brix, VIVO mini, RPi3, Debian Jessie, ZME_UZB1
HM-CFG-LAN, HM-MOD-UART-WIFI, HUE, HarmonyHub, JeeLink, CO20
Hyperion auf RPi Zero W, Sonos, viel Z-Wave und HM
alles per HomeKit steuerbar
MAINTAINER: 22_HOMEMODE, 98_Hyperion, 98_FileLogConvert

Offline Reinerlein

  • Developer
  • Hero Member
  • ****
  • Beiträge: 1779
Antw:mal wieder split Verwirrung
« Antwort #9 am: 20 März 2017, 15:27:20 »
Hi Dan,

nicht ganz.
Bei dem Sonderfall " " wird erst ein TrimLeft() gemacht, und dann bei \s+ getrennt...
split " ",$str
split /\s+/, trimleft($str)
Das letzte split macht was ganz anderes (sofern es so überhaupt funktionieren würde, ich würde mal sagen nicht, da [] eine Zeichenklasse beschreibt, und du keinen Quantifizierer dort reinschreiben darfst)... Es würde wohl an mindestens einem Leerzeichen oder an mindestens einem Tabulator oder an mindestens einem Cariage Return oder oder mindestens einem Newline trennen. Keine Mischung dieser Zeichen(!). Vielleicht hattest du sowas gemeint:?
split /[ \t\r\n]+/,$str
Da fehlt dann aber immer noch der vorhergehende trimleft()...

Grüße
Reiner

Online DeeSPe

  • Developer
  • Hero Member
  • ****
  • Beiträge: 3400
  • Wer anderen eine Bratwurst brät...
Antw:mal wieder split Verwirrung
« Antwort #10 am: 20 März 2017, 15:35:36 »
Ich denke nun ist es klar.
Schön wenn man es endlich versteht.

Danke nochmal Reiner.

Gruß
Dan
FHEM 5.8, Brix, VIVO mini, RPi3, Debian Jessie, ZME_UZB1
HM-CFG-LAN, HM-MOD-UART-WIFI, HUE, HarmonyHub, JeeLink, CO20
Hyperion auf RPi Zero W, Sonos, viel Z-Wave und HM
alles per HomeKit steuerbar
MAINTAINER: 22_HOMEMODE, 98_Hyperion, 98_FileLogConvert

 

decade-submarginal