Hilfe bei einem regulären Ausdruck

Begonnen von TomLee, 25 August 2020, 17:04:33

Vorheriges Thema - Nächstes Thema

TomLee

Hallo,

mir gibt ein get Unifi voucherList 7d1x folgendes zurück:

==================================================================
code = 4471539270
duration = 10080
note = 7d1x
quota = 1
status = VALID_ONE
status_expires = 0
used = 0
==================================================================
code = 5935744848
duration = 10080
note = 7d1x
quota = 1
status = VALID_ONE
status_expires = 0
used = 0
==================================================================
Count: 2


Es gibt ein Reading -AP_Wohnzimmer_essid mit dem Inhalt:

FBF,Gast1,FBF,Gast1


Ein userreadings :

voucher_7d1x:-VC_7d1x:.* {my @ar = (fhem("get Unifi voucherList 7d1x") =~ m,code.=.([0-9]{10}),g);
my @array = split(",",ReadingsVal("Unifi","-AP_Wohnzimmer_essid","unknown"));
unshift(@ar,$array[1]);my $ar = join(',',@ar)}


macht mir daraus diese Liste:

Gast1,4471539270,5935744848


Ich hätte gerne in der Liste noch einmal den Wert von duration aus dem get von oben.

Mit dem regex
code.=.([0-9]{10})|duration.=.([0-9]{5})
passt das mehr oder weniger auch auf regex101.

Es gibt 4 Matches mit jeweils einer Group.

Warum macht mir aber mein Code (im ersten Schritt)
{my @ar = (fhem("get Unifi voucherList 7d1x") =~ m,code.=.([0-9]{10})|duration.=.([0-9]{5}),g);;my $ar = join(',',@ar)}

das hier daraus :

4471539270,,,10080,5935744848,,,10080


?

Weitere Frage wäre ob man mit einem Ausduck auch veranlassen kann doppelte Matches zu einem Match zusammenzufassen ?
Also dann 3 Matches mit je einer Group zu erhalten.
Mit dem Ergebnis:
code = 1687752668
duration = 30240
code = 1319214911


Weitere Frage:

{my @ar = (fhem("get Unifi voucherList 7d1x") =~ m,code.=.([0-9]{10}),g);;my $ar = join(',',@ar)}


gibt
4471539270,5935744848
zurück.

Warum kann ich hier
{my @ar = (fhem("get Unifi voucherList 7d1x") =~ m,code.=.([0-9]{10}),g);;$1}
mit der Ersatzsequenz $n nur auf $1 zugreifen ? $0 gibt fhem.pl zurück,$2 einfach nix, auch nicht im Log.

Gruß

Thomas

crusader

#1
code.=.([0-9]{10})|duration.=.([0-9]{5})

Das Ergebnis dürfte wohl von der jeweiligen Perl-Version abhängen. Bei mir bekomme ich da gar keinen Match.
Eindeutiger wäre:
(?s)code.=.([0-9]{10}).*?duration.=.([0-9]{5})

Da bekomme ich vier Matches, die man dann auch per join verbinden kann.
Die $n-Variablen laufen bei mir auch nicht über multiple-Matches. Es werden also nur fortlaufende $n-Variablen befüllt bei separaten Capture-Groups, nicht bei multiplen Matches einer Capture-Group.

Die fangen übrigens bei $1 an.
$0 ist der Programm-Name.

TomLee

#2
Da bekomme ich vier Matches, die man dann auch per join verbinden kann.

Danke. Danke.

Hab mit regex gar nix am Hut, passt erstmal besser wie das was ich mir zusammengereimt habe.

Die Frage die ich mir halt stelle ob drei Matches auch mit regex möglich wären, brauch die duration ja nur einmal.

code = 1687752668
duration = 30240
code = 1319214911



crusader

Innerhalb des Regex-Ausdrucks sicher nicht.

Aber warum dann überhaupt die Trickserei mit gemeinsamem Capture von 'Code' und 'Duration' ?

Mach daraus doch zwei Variablen:
m/code.=.([0-9]{10})/g
enthält alle Codes und
m/duration.=.([0-9]{5})/
enthält die erste Duration.
Danach beide mit join zusammenführen.

TomLee

Mach daraus doch zwei Variablen:
Danach beide mit join zusammenführen.


Ja, klar.

Das ist mehr oder weniger mein Ausgangspunkt, mein Gedanke war das ist ein Umweg.

crusader

Ja gut.

Wenn Du nur einmal matchen willst, musst Du halt mit dem join-Ausdruck für das erhaltene Array arbeiten:

join ',',@ar[grep !($_ % 2), 0..$#ar],@ar[1]
enthält alle Codes und am Ende die erste Duration.

TomLee

Wow, Wow, du Fuchs du.

Ich will das verstehen, soweit bin ich aber noch nicht.

Erschwerend für mich, du nimmst irgendwie glaub ich von allem die kurze Variante ohne Klammern.
Kannst du bitte in kurzen Worten erläutern was ab hier @ar[grep !($_ % 2), 0..$#ar] genau passiert oder verständliche Doku nennen an der ich mir das ableite, es ist mir trotz Code unklar was genau passiert 8)
grep ist irgendwie schon klar, was macht das Prozenzeichen warum 2, # hab ich glaub ich noch nie gelesen.
Ich muss mich dazu mehr einlesen um das zu verstehen.


Da ist ein Denkfehler drin, denk ich, es sollte genau andersrum sein
{my @ar = (fhem("get Unifi voucherList 7d1x") =~ m,(?s)code.=.([0-9]{10}).*?duration.=.([0-9]{5}),g);
my @array = split(",",ReadingsVal("Unifi","-AP_Wohnzimmer_essid","unknown"));
unshift(@ar,$array[1]);join ',',@ar[grep !($_ % 2), 0..$#ar],@ar[1]}

ergibt jetzt
Gast1,10080,10080,4471539270


crusader

$#ar ist der letzte Index des Arrays.
@ar[0..$#ar] ist ein neues Array, das mit den Elementen von 0 bis zum letzten Index befüllt wird. Die Laufvariable für diesen Prozess ist als $_ zugänglich.
Mit grep kann man die zulässigen Indizes filtern, in diesem Fall auf alle Werte, deren modulo2-Operation nicht null ist, also alle ungeraden.


ZitatDa ist ein Denkfehler drin, denk ich, es sollte genau andersrum sein.

Na ja, weil Du vorher schon den Gast ins Array geschoben hast.
Machs doch gleich in einem Schwung:

join ',',$array[1],@ar[grep !($_ % 2), 0..$#ar],@ar[1]

TomLee

#8
Es gab noch die Warnung hier:

2020.08.26 13:21:10 1: PERL WARNING: Scalar value @ar[1] better written as $ar[1] at (eval 1479406) line 3.
2020.08.26 13:21:10 3: eval: {my @ar = (fhem("get Unifi voucherList 7d1x") =~ m,(?s)code.=.([0-9]{10}).*?duration.=.([0-9]{5}),g);
my @array = split(",",ReadingsVal("Unifi","-AP_Wohnzimmer_essid","unknown"));
join ',',$array[1],@ar[1]/1440,@ar[grep !($_ % 2), 0..$#ar]}


Hab ich gemacht und sie ist jetzt weg.