Regex i Perl vägrar spotta ut match

Permalänk
Medlem

Regex i Perl vägrar spotta ut match

Tjena!

Jag sitter och knackar ihop en uppgift i skolan, men blir tokig på det här med regex. Jag har försökt att separera en sträng ifrån ett systemkommando för att infoga i en hash.

Outputen ifrån systemkommandot talar om hur många gånger en användare har loggat in där användarnamnet följer olika standarder, ex:

33 karl
14 hanna
53 k18daad

Jag vill alltså sära på antalet inlogg och vem som har gjort inloggen. Jag har felsökt hela vägen ner till mitt regex och är säker på att felet antingen ligger i regex-uttrycket, eller i mitt försök att lägga matchningen i en variabel - där det senare är det mest troliga felet.

Exempel på kod jag försökt med:

foreach(@log){

$_ =~ /(^[0-9]+) ([a-zA-Z0-9]+$)/;
my $key = $2;
my $value = $1;
print "Key = $2 value = $1\n";
}

Jag har försökt lite olika variationer på detta, men resultatet är allt som oftast att variablerna får värdet "1", om det finns i strängen. Vad tusan gör jag för fel?

Tack på förhand!

Visa signatur

+++ Divide By Cucumber Error. Please Reinstall Universe And Reboot +++

"Real stupidity beats artificial intelligence every time." - Terry Pratchett, Hogfather

Permalänk
Medlem

Jag kan inte Perl, men prova använda RegExr.com för att fastställa att ditt regex fungerar. Därefter felsöker du annat

Permalänk
Hedersmedlem

Hm, hur ser övriga koden ut? Jag körde följande:

~ $ cat > data.txt 33 karl 14 hanna 53 k18daad ~ $ cat > test.pl foreach(<>){ $_ =~ /(^[0-9]+) ([a-zA-Z0-9]+$)/; my $key = $2; my $value = $1; print "Key = $2 value = $1\n"; } ~ $ perl test.pl data.txt Key = karl value = 33 Key = hanna value = 14 Key = k18daad value = 53 ~ $

Jag ändrade alltså enbart så att den loopar över input rad för rad, istället för arrayen log. Felet lär vara i hur du samlar in datan till arrayen.

Visa signatur

Asus ROG STRIX B550-F / Ryzen 5800X3D / 48 GB 3200 MHz CL14 / Asus TUF 3080 OC / WD SN850 1 TB, Kingston NV1 2 TB + NAS / Corsair RM650x V3 / Acer XB271HU (1440p165) / LG C1 55"
Mobil: Moto G200

Permalänk
Medlem

@Tommy: Jag har använt rubular.com i min felsökning är sidan du föreslog ett bättre alternativ? Jag ska se om jag får samma resultat!

@Thomas: Resten ser ut såhär:

Jag har som sagt felsökt och får förväntad output i form av del hela strängen när jag skriver:

foreach(@log){

print "$_\n";
}

Just den här delen ingår i ett större script där andra matchningar görs och jag är medveten om att $1 då kan skapa problem, men samma resultat följer användandet av egendeklarerade variabler.

Visa signatur

+++ Divide By Cucumber Error. Please Reinstall Universe And Reboot +++

"Real stupidity beats artificial intelligence every time." - Terry Pratchett, Hogfather

Permalänk
Hedersmedlem

@scienta: Hmm, i den versionen i bilden så saknas mellanslag mellan siffran och användarnamnet, och det matchar alltid bara exakt en siffra för antalet inloggningar. Regexet från första inlägget ser bättre ut. Jag skulle dock rekommendera \s+ istället för bara mellanslag, så att det även fungerar om det vore två mellanslag, en tabb, eller liknande istället.

Jag är egentligen inte särskilt hemma på Perl alls. Jag skulle i detta läget dock köra

use Data::Dumper; [...] print Dumper(\@log);

och se exakt hur innehållet ser ut.

Visa signatur

Asus ROG STRIX B550-F / Ryzen 5800X3D / 48 GB 3200 MHz CL14 / Asus TUF 3080 OC / WD SN850 1 TB, Kingston NV1 2 TB + NAS / Corsair RM650x V3 / Acer XB271HU (1440p165) / LG C1 55"
Mobil: Moto G200

Permalänk
Medlem

@Thomas: \s+ gjorde faktiskt skillnad och jag fick nu ut delar utav den output jag vill ha. Så något fel verkar det vara på regex.

Output ifrån Dumper visar att arrayen ser ut precis som förväntat, med en sträng för varje element.

EDIT: hittade felet i mitt test, det saknades ett "+". Nu verkar uttrycket fungera, då ska jag testa att lägga matchningarna i en hash.

Då borde det väl fungera med:

my %hash

$hash{$2} = "$1";

?

Visa signatur

+++ Divide By Cucumber Error. Please Reinstall Universe And Reboot +++

"Real stupidity beats artificial intelligence every time." - Terry Pratchett, Hogfather

Permalänk
Geeks
Jobbar med data

Nu ser ju din regex ut att fungera, men jag har aldrig tidigare sett någon lägga start och slutankaret på ovan nämnda positioner. Normalt skrivs dem såhär:

^([0-9]+)\s+([a-zA-Z0-9]+)$

https://regex101.com/r/6GeLF9/1/
Koden nedan kommer från "Code generator > perl".

use strict; my $str = '33 karl'; my $regex = qr/^([0-9]+)\s+([a-z0-9]+)$/ip; if ( $str =~ /$regex/ ) { print "Whole match is ${^MATCH} and its start/end positions can be obtained via \$-[0] and \$+[0]\n"; # print "Capture Group 1 is $1 and its start/end positions can be obtained via \$-[1] and \$+[1]\n"; # print "Capture Group 2 is $2 ... and so on\n"; } # ${^POSTMATCH} and ${^PREMATCH} are also available with the use of '/p' # Named capture groups can be called via $+{name}

https://regex101.com/r/6GeLF9/2
Och hur man döper dem.

use strict; my $str = '33 karl'; my $regex = qr/^(?<id>[0-9]+)\s+(?<name>[a-z0-9]+)$/ip; if ( $str =~ /$regex/ ) { print "Whole match is ${^MATCH} and its start/end positions can be obtained via \$-[0] and \$+[0]\n"; # print "Capture Group 1 is $1 and its start/end positions can be obtained via \$-[1] and \$+[1]\n"; # print "Capture Group 2 is $2 ... and so on\n"; } # ${^POSTMATCH} and ${^PREMATCH} are also available with the use of '/p' # Named capture groups can be called via $+{name}

Permalänk
Medlem

@jreklund: Jag var osäker på vart de skulle ligga och jag resonerade att de var en del av "hela" uttrycket - dvs. inom parentes. Jag fick det hela att fungera med hjälpen jag fick tidigare (tack så hemskt mycket, förövrigt) - men sitter nu med ett nytt problem.

Jag ska skapa en array med hashes ifrån inputen ´netstat -lntup´, men jag kommer inte alls på hur jag ska namnge dessa hashes på ett unikt sätt i en foreach-loop. Jag har inte riktigt kommit på vad tanken är det, när det borde fungerat likabra att göra en ensam hash med multipla värden för varje nyckel.

Uppgiften lyder:
"The function has to return an array (one element per listening socket)
and each element is a hash containing the requested information per socket."

Jag försökte att använda någon form av räknare för att namnge varje hash individuellt, men det verkar inte gå att använda en variabel i deklarationen av namnet på hashen. Någon idé ?

Visa signatur

+++ Divide By Cucumber Error. Please Reinstall Universe And Reboot +++

"Real stupidity beats artificial intelligence every time." - Terry Pratchett, Hogfather