greenFox has asked for the wisdom of the Perl Monks concerning the following question:

I have a requirement to parse the etime field of solaris ps command. It looks like this (from man ps) [[dd-]hh:]mm:ss The leading two fields (days and hours) are optional. My first attempt was a re which looks pretty nasty:
for ($etime){ my ($dd,$hh,$mm,$ss)=() # see man ps etime looks like [[dd-]hh:]mm:ss if ( /^(?:(?:(\d{1,2})-){0,1})(?:(?:(\d{2}):){0,1})(\d{1,2}):(\d{2}) +$/ ){ $dd = $1 || ''; $hh = $2 || ''; $mm = $3; $ss = $4; $etime_secs= $ss+($mm*60)+($hh*60*60)+($dd*24*60*60); } }
I am sure the re can be improved but really the problem seemed to be begging for a split:
for ($etime){ # see man ps etime looks like [[dd-]hh:]mm:ss # if either $dd and $hh are not present then they will eat # up the $mm & $ss so split on a non digit and reverse it: my ($ss, $mm, $hh, $dd)= reverse split /\D/; $hh += 0; # stop warning as $hh may not be initialised $dd += 0; # same as $hh :) $etime_secs= $ss+($mm*60)+($hh*60*60)+($dd*24*60*60); }
Which is much nicer though I am just itching to get rid of the lines to make sure $hh and $dd are initialised :) Can any-one see a better way?

--
Life is a tale told by an idiot -- full of sound and fury, signifying nothing. William Shakespeare, Macbeth

Replies are listed 'Best First'.
Re: parsing etime field from solaris ps
by sauoq (Abbot) on May 30, 2003 at 02:57 UTC

    I think a regex makes more sense in this case. Yours can be cleaned up a bit though.

    my ($dd,$hh,$mm,$ss) = /^(?:(\d\d)-)?(?:(\d\d):)?(\d\d):(\d\d)$/;
    -sauoq
    "My two cents aren't worth a dime.";
    

      I can't believe I wrote {0,1} :) Your clean up is not quite right though- probably because I didn't give enough information to start with. $dd is not zero padded and whilst the man page says $mm is zero padded (on solaris 8 at least) it isn't zero padded when the etime is less than an hour.

      /^(?:(\d+)-)?(?:(\d+):)?(\d+):(\d+)$/;

      which is way better than what I had, thanks.

      --
      Life is a tale told by an idiot -- full of sound and fury, signifying nothing. William Shakespeare, Macbeth

Re: parsing etime field from solaris ps
by BrowserUk (Patriarch) on May 30, 2003 at 03:17 UTC

    Here's a different approach, better, worse, useful to you is your call:)

    #! perl -slw use strict; my $re_etime = qr[ (?{ our $ETIME = 0 }) (?: (\d{2}) (?{ $ETIME = 24 * $^N||0 }) - )? (?: (\d{2}) (?{ $ETIME = 60 * ($ETIME + $^N||0) }) : )? (\d{2}) (?{ $ETIME = 60 * ($ETIME + $^N) }) : (\d{2}) (?{ $ETIME += $^N }) ]x; for my $test ( '25:41', '19:25:41', '11-19:25:41' ) { our $ETIME; print "$test => $ETIME" if $test =~ $re_etime; } __DATA__ D:\Perl\test>261741 25:41 => 91541 19:25:41 => 69941 11-19:25:41 => 1020341

    I hope the math is right:)

    The regex explained


    Examine what is said, not who speaks.
    "Efficiency is intelligent laziness." -David Dunham
    "When I'm working on a problem, I never think about beauty. I think only how to solve the problem. But when I have finished, if the solution is not beautiful, I know it is wrong." -Richard Buckminster Fuller


Re: parsing etime field from solaris ps
by Enlil (Parson) on May 30, 2003 at 02:49 UTC
    Change This:
    $hh += 0; # stop warning as $hh may not be initialised $dd += 0; # same as $hh :) $etime_secs= $ss+($mm*60)+($hh*60*60)+($dd*24*60*60);
    To This:
    $etime_secs= $ss+($mm*60)+($hh?$hh*60*60:0)+($dd?$dd*24*60*60:0);
    Note that undefined or 0, it does not matter that it returns 0 with the ternary operator (0*anything = 0, anyway).

    -enlil