J'ai un fichier de données qui affiche les données suivantes:
#!/usr/bin/perl open(FILE, $ARGV[0]) or die ("Error Found: $!"); while ( $line = <FILE> ) { ($login, $time) = split('\(', $line); # print "Time: $time"; ($hour,$m) = split('\:',$time); # print "Hour: $hour\n"; if ( $hour <= 16 ) { # print "Found: $hour\n"; $n++; } } print "There were $n logins that were still on the system after 16:00 on May 26.\n"; close(FILE);
J'ai créé un script perl qui est supposé afficher le nombre de connexions encore connectées après 16h00 le 26 mai. C'est ce que j'ai jusqu'à présent et je n'arrive pas à comprendre comment afficher le nombre correct de connexions qui sont 5.
cfs264su pts/6 x.x.x.x.x Tue May 26 16:46 - 19:21 (02:34) cfs264su pts/6 x.x.x.x.x Tue May 26 16:30 - 16:46 (00:15) cfs264su pts/6 x.x.x.x.x Tue May 26 16:19 - 16:30 (00:10) cfs264su pts/6 x.x.x.x.x Tue May 26 14:59 - 15:30 (00:31) cfs264su pts/5 x.x.x.x.x Tue May 26 14:40 - 17:13 (02:33) cfs264su pts/1 x.x.x.x.x Tue May 26 14:02 - 19:06 (05:03) cfs264su pts/6 x.x.x.x.x Tue May 26 10:36 - 13:18 (02:41) cfs264su pts/5 x.x.x.x.x Tue May 26 10:22 - 12:45 (02:23) cfs264su pts/1 x.x.x.x.x Tue May 26 08:45 - 12:12 (03:27) cfs264su pts/5 x.x.x.x.x Tue May 26 00:34 - 01:28 (00:54)
3 Réponses :
J'ai enfin compris. le split devait utiliser / - /
#!/usr/bin/perl open(FILE, $ARGV[0]) or die ("Error Found: $!"); while ( $line = <FILE> ) { ($login, $time) = split(/ - /, $line); # print "Time: $time"; ($hour,$m) = split('/ - /:',$time); # print "Hour: $hour\n"; if ( $hour < 16 ) { # print "Found: $hour\n"; $n++; } } print "There were $n logins that were still on the system after 16:00 on May 26.\n"; close(FILE);
Merci!
Non ... split ('/ - /:', $time)
est très incorrect. Vous ne l'avez pas dans votre entrée, donc cette ligne ne fait rien. Cela fonctionne parce que l'heure de déconnexion est la première dans $time
, donc l'opération <
essaiera de lancer par exemple 14:40 - 17:13 (02:33)
en un nombre, et se terminant par 14
, ce qui fonctionne pour vous. Je crois que je vous ai également dit d'ajouter use strict; use warnings
dans votre code pour éviter de faire de simples erreurs. Apprendre Perl sans cela, c'est comme essayer de l'apprendre avec les yeux bandés.
L'exemple de code suivant illustre l'une des manières possibles.
Algorithme:
$start
et $end
$record->{@fields}
avec des champs comme clés%login
HoA %login
avec l' ID utilisateur comme clé$start
et $end
$count
$count
à la finCourir comme:
script.pl user '[start]' '[end]'
Linux script.pl user '[start]' '[end]'
script.pl user "[start]" "[end]"
Windows script.pl user "[start]" "[end]"
USER: cfs264su START: Tue May 26 10:00:00 2020 END: Tue May 26 15:00:00 2020 --------------------------------------------- IN: Tue May 26 14:59:00 2020 OUT: Tue May 26 15:30:00 2020 --------------------------------------------- IN: Tue May 26 14:40:00 2020 OUT: Tue May 26 17:13:00 2020 --------------------------------------------- IN: Tue May 26 14:02:00 2020 OUT: Tue May 26 19:06:00 2020 --------------------------------------------- IN: Tue May 26 10:36:00 2020 OUT: Tue May 26 13:18:00 2020 --------------------------------------------- IN: Tue May 26 10:22:00 2020 OUT: Tue May 26 12:45:00 2020 --------------------------------------------- Logged in: 5 times
Production
use strict; use warnings; use feature 'say'; use Date::Parse; my $user = shift || 'cfs264su'; my $start = shift || 'May 26 10:00 2020'; my $end = shift || 'May 26 15:00 2020'; $start = date2epoch($start); $end = date2epoch($end); say 'USER: ' . $user; say 'START: ' . scalar localtime $start; say 'END: ' . scalar localtime $end; say '-' x 45; my %login; my @fields = qw/id pts what wday month mday in out duration/; my $count; while( <DATA> ) { my($id, $record); $record->@{@fields} = split "[- ()]+"; $id = $record->{id}; delete $record->{id}; push @{$login{$id}}, $record; } for( @{$login{$user}} ) { my $in = date2epoch(join ' ', $_->@{qw/month mday in/}); my $out = date2epoch(join ' ', $_->@{qw/month mday out/}); if( $in >= $start && $in <= $end) { ++$count; say 'IN: ' . scalar localtime $in; say 'OUT: ' . scalar localtime $out; say '-' x 45; } } say "Logged in: $count times"; exit; sub date2epoch { my $date = shift; return str2time($date); } __DATA__ cfs264su pts/6 x.x.x.x.x Tue May 26 16:46 - 19:21 (02:34) cfs264su pts/6 x.x.x.x.x Tue May 26 16:30 - 16:46 (00:15) cfs264su pts/6 x.x.x.x.x Tue May 26 16:19 - 16:30 (00:10) cfs264su pts/6 x.x.x.x.x Tue May 26 14:59 - 15:30 (00:31) cfs264su pts/5 x.x.x.x.x Tue May 26 14:40 - 17:13 (02:33) cfs264su pts/1 x.x.x.x.x Tue May 26 14:02 - 19:06 (05:03) cfs264su pts/6 x.x.x.x.x Tue May 26 10:36 - 13:18 (02:41) cfs264su pts/5 x.x.x.x.x Tue May 26 10:22 - 12:45 (02:23) cfs264su pts/1 x.x.x.x.x Tue May 26 08:45 - 12:12 (03:27) cfs264su pts/5 x.x.x.x.x Tue May 26 00:34 - 01:28 (00:54)
Une approche simple utilisant Time :: Piece .
#!/usr/bin/perl use strict; use warnings; use feature 'say'; use Time::Piece; # The format of the dates and times that we're dealing with my $fmt = '%b %d %H:%M'; # Store the count my $count; # Get a Time::Piece object that represents our cut-off time my $cutoff = Time::Piece->strptime('May 26 16:00', $fmt); # Note: I'm reading from DATA here. It's an easy way to # prototype stuff without having to deal with opening files while (<DATA>) { # Split the data on whitespace # Pull out columns 4, 5 and 8 # Join them with a space - which gives us the end date/time my $end_str = join ' ', (split /\s+/)[4, 5, 8]; # Parse that string into a Time::Piece object my $end = Time::Piece->strptime($end_str, $fmt); # Increment the counter if this date/time is # greater than the cut-off $count++ if $end > $cutoff; } say $count; __DATA__ cfs264su pts/6 x.x.x.x.x Tue May 26 16:46 - 19:21 (02:34) cfs264su pts/6 x.x.x.x.x Tue May 26 16:30 - 16:46 (00:15) cfs264su pts/6 x.x.x.x.x Tue May 26 16:19 - 16:30 (00:10) cfs264su pts/6 x.x.x.x.x Tue May 26 14:59 - 15:30 (00:31) cfs264su pts/5 x.x.x.x.x Tue May 26 14:40 - 17:13 (02:33) cfs264su pts/1 x.x.x.x.x Tue May 26 14:02 - 19:06 (05:03) cfs264su pts/6 x.x.x.x.x Tue May 26 10:36 - 13:18 (02:41) cfs264su pts/5 x.x.x.x.x Tue May 26 10:22 - 12:45 (02:23) cfs264su pts/1 x.x.x.x.x Tue May 26 08:45 - 12:12 (03:27) cfs264su pts/5 x.x.x.x.x Tue May 26 00:34 - 01:28 (00:54)
après devrait être 3, non? Et l'heure est le hh: mm juste après le «26 mai» ... Dans les (), c'est la durée.
C'est une mauvaise façon d'utiliser la
split
. Aussi, ne pas utiliseruse strict; use warnings
est une mauvaise idée.J'ai oublié de mentionner que je suis très nouveau dans le script perl et c'est une question de devoir avec laquelle je me bats. Je suis complètement perdu à ce stade.
Votre logique ici est que le "temps de connexion" doit être supérieur à 16 s'ils sont toujours connectés après 16h00. Ce n'est pas vrai. Il n'y a personne avec plus de 16 heures. Vous devez vérifier l'heure de déconnexion.
Que pouvez-vous nous dire de l'apport? Est-il à largeur fixe ou séparé par des tabulations? Si c'est ce dernier, vous pouvez utiliser split pour séparer les colonnes. Si c'est le premier, vous pouvez utiliser unpack ou substr.