mal wieder split Verwirrung

Begonnen von DeeSPe, 19 März 2017, 16:30:53

Vorheriges Thema - Nächstes Thema

DeeSPe

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
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

zap

Ein " " trennt bein einzelnen Leerzeichen. Ein \s auch, ein \s+ hingegen bei 1 oder mehreren aufeinanderfolgenden
2xCCU3, Fenster, Rollläden, Themostate, Stromzähler, Steckdosen ...)
Entwicklung: FHEM auf AMD NUC (Ubuntu)
Produktiv inzwischen auf Home Assistant gewechselt.
Maintainer: FULLY, Meteohub, HMCCU, AndroidDB

DeeSPe

Zitat von: zap am 19 März 2017, 16:34:22
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
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

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
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

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
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

Markus Bloch

#5
Hallo Dan,

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

Zitat von: http://perldoc.perl.org/functions/split.htmlAs 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
Developer für Module: YAMAHA_AVR, YAMAHA_BD, FB_CALLMONITOR, FB_CALLLIST, PRESENCE, Pushsafer, LGTV_IP12, version

aktives Mitglied des FHEM e.V. (Technik)

DeeSPe

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
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

Reinerlein

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

DeeSPe

#8
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
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

Reinerlein

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

DeeSPe

Ich denke nun ist es klar.
Schön wenn man es endlich versteht.

Danke nochmal Reiner.

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