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

fellow monks,
I am trying to left justify and condense multiple spaces the output from the "ps" command. I just can't get left justification to work. Help. My code is posted below:
#!/usr/bin/perl # # ps format $PSfmt = "\"pid,ppid,pgid,user\""; # ps command $PScmd = `ps -ef -o $PSfmt`; # # run the command, output into array @PSarray = $PScmd ; # # eliminate leading spaces, and condense spaces for (@PSarray) {s/^\s+//; s/ +/ /g; print "$_ \n"; } exit;
I can do this with "sed" but I prefer to stick to using Perl.
for $rec (@PSarray) { $rec = `echo "$rec"|tr -s ' '|sed 's/^ //'`; print "$rec\n"; } exit;
I hope someone can show me how to do this in Perl.
Thanks in advance.

Replies are listed 'Best First'.
Re: manipulation of ps command output
by iguanodon (Priest) on Mar 09, 2004 at 23:20 UTC
Re: manipulation of ps command output
by borisz (Canon) on Mar 09, 2004 at 21:20 UTC
    #!/usr/bin/perl # # ps format $PSfmt = "\"pid,ppid,pgid,user\""; # ps command $_ = `ps -ef -o $PSfmt`; # # eliminate leading spaces, and condense spaces s/^\s+//gm; s/ +/ /gm; print "$_ \n";
    Boris
Re: manipulation of ps command output
by matija (Priest) on Mar 09, 2004 at 21:18 UTC
    This is your problem line:
    @PSarray = $PScmd ;
    By that point, $PScmd already contains the result of the command. You are assigning all the lines to $PSarray[0].

    There are two ways to fix your code, that I can see:

    • Split the result into lines: @PSarray=split(/\n/,$PScmd);
    • Or do the substitution on the whole string, but change how the RE engine interprets it: s/^\s+//m. (The m modifier tells the regexp engine to make ^ and $ match start and end of line instead of start and end of string).
Re: manipulation of ps command output
by TilRMan (Friar) on Mar 10, 2004 at 04:57 UTC
    While matija has your bugfix, you could try the line-by-line approach:
    open PS, 'ps -ef -o pid,ppid,pgid,user |' or die; while (<PS>) { tr/ //s; s/^ //; print; } close PS or die;
    but I think what you really want is split and join (or $" or $,). Some golfing gives:
    #!/bin/sh ps -ef -o pid,ppid,pgid,user | /usr/bin/perl -lape '$_="@F"'

    -- 
    LP^>

Re: manipulation of ps command output
by Fletch (Bishop) on Mar 09, 2004 at 21:17 UTC

    Erm, have you tried perl's tr///?

    $_ = "a b c"; tr/ / /s; print;
Re: manipulation of ps command output
by captain_haddock (Novice) on Mar 11, 2004 at 13:55 UTC
    If you are using a Un*x platform, you may want to look at Proc::ProcessTable. This is from the perldoc....
    # A cheap and sleazy version of ps use Proc::ProcessTable; $FORMAT = "%-6s %-10s %-8s %-24s %s\n"; $t = new Proc::ProcessTable; printf($FORMAT, "PID", "TTY", "STAT", "START", "COMMAND"); foreach $p ( @{$t->table} ){ printf($FORMAT, $p->pid, $p->ttydev, $p->state, scalar(localtime($p->start)), $p->cmndline); }
Re: manipulation of ps command output
by zentara (Cardinal) on Mar 10, 2004 at 16:34 UTC
    Some wise old monk, showed us this awhile back, a different approach.
    #!/usr/bin/perl for (split '\n',qx(ps -u $> -o pid,ppid,pgid,user --no-headers)) { ($pid, $ppid, $pgid,$user) = unpack "a5 x a5 x a5 x a20",$_; print "$pid $ppid $pgid $user\n"; }

    I'm not really a human, but I play one on earth. flash japh