Xref: utzoo comp.unix.questions:30832 comp.lang.perl:5117 Path: utzoo!utgpu!news-server.csri.toronto.edu!bonnie.concordia.ca!uunet!elroy.jpl.nasa.gov!jpl-devvax!lwall From: lwall@jpl-devvax.jpl.nasa.gov (Larry Wall) Newsgroups: comp.unix.questions,comp.lang.perl Subject: Re: Searching the output of last Keywords: last awk sed perl C whatever Message-ID: <1991Apr29.072206.5621@jpl-devvax.jpl.nasa.gov> Date: 29 Apr 91 07:22:06 GMT References: <1991Apr28.070748.5279@bradley.bradley.edu> <1991Apr29.053721.8733@agate.berkeley.edu> <1991Apr29.021236.12132@casbah.acns.nwu.edu> <1991Apr29.040325.1822@athena.mit.edu> <1991Apr29.043041.20454@casbah.acns.nwu.edu> Reply-To: lwall@jpl-devvax.JPL.NASA.GOV (Larry Wall) Organization: Jet Propulsion Laboratory, Pasadena, CA Lines: 64 In article <1991Apr29.053721.8733@agate.berkeley.edu> raymond@math.berkeley.edu (Raymond Chen) writes: : In article <1991Apr29.043041.20454@casbah.acns.nwu.edu>, navarra@casbah (John 'tms' Navarra) writes: : : >how bout setting up a program that... looks thru utmp by doing a last : >| grep time (might be slow) ... then increments it by one for interval loops. : ^^^^^^^^^^^^^ : my vote for understatement of the day. It is not unheard : of for people to be logged in for days at a time. Incrementing by one means : you have to perform thousands of greps. : : [For comp.lang.perlers, the problem is to write a progral called `whenwho' : which prints out everybody who was logged on at the time indicated on the : command line.] : : Try this. Hacked up in 15 minutes, minimally tested. Part of the : problem is that you never know if you've searched backwards far : enough, because there might be someone who has been logged on : continuously for the past five months. In the original problem, : however, we are told that the wtmp goes back only as far as around 5am : the day of the run, so this isn't an issue. : [Script that reads wtmp directly omitted.] If we can assume nobody is logged in overnight (or that records aren't kept), then I'd just process the output of "last", like this: #!/usr/bin/perl $when = sprintf("%02d:%02d", shift =~ /^(\d+):?(\d\d)$/); $today = (localtime())[3]; open(LAST, "last |"); while () { next if length() < 60; ($date,$in,$out) = unpack(x44A2xA5x3A5,$_); last if $date != $today; print if $when ge $in && $when le $out; } Not quite a one-liner, but getting closer... Hmm... If we throw out the claptrap to check for todayness, and force people to enter exactly \d\d:\d\d for the time, we can say $w=shift;@ARGV="last|";$w ge substr($_,47,5)&&$w lt substr($_,55)&&print while<> Hmm... No reason not to use a regular expression... $w=shift;@ARGV="last|";/.{47}(.{5})...(.*)/&&$w ge$1&&$w lt$2&&print while<> Hmm... We can dump two of those spaces that separate alphanumeric tokens... $$=shift;@ARGV="last|";/.{47}(.{5})...(.*)/&&$$ge$1&&$$lt$2&&print while<> Hmm... We can assume that the first field contains the first colon... $$=shift;@ARGV="last|";/(..:..)...(.*)/&&$$ge$1&&$$lt$2&&print while<> I don't see how to make that shorter, offhand. At least not in Perl alone. Combining with shell, we can say last|perl -pe '$_ x=/(..:..)...(.*)/&&"'$1'"ge$1&&"'$1'"lt$2' That's gonna be tough for Randal to beat... :-) Larry