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

Hello kind Monks,

I am trying to retrieve from a "ps -ef" specific strings using a simple regex.
My code looks something like that:

my $logname = `logname`; chomp($logname); my $output = `ps -ef | grep $logname`; if ($output =~ /.*\/export\/home\/$logname\/(.*)\/bin\/.*/m){ print "$`\n"; }

with the output being something like:

root 28834 28833 0 Aug25 ? 00:00:00 login -- mylogname2
root 29853 29852 0 Aug25 ? 00:00:00 login -- mylogname2
root 5379 5378 0 Aug26 ? 00:00:00 login -- mylogname2
root 5454 5453 0 Aug26 ? 00:00:00 login -- mylogname2
509 6710 1 0 00:20 ? 00:00:28 /export/home/mylogname/folder1/bin/binary
509 6729 1 0 00:35 ? 00:00:11 /export/home/mylogname/folder2/bin/binary
522 7996 1 0 07:00 ? 00:00:07 /export/home/mylogname2/folder1/bin/binary
509 7997 1 0 07:00 ? 00:00:01 /export/home/mylogname/folder3/bin/binary
522 8045 1 0 07:02 ? 00:00:02 /export/home/mylogname2/folder4/bin/binary

However the result of the print gives me the first four line while I am trying to folder1, folder2 and folder3 since my logname is "mylogname".

What am I doing wrong?

Thank you

PS: I tried also with a regex like that:
^.*\/export\/home\/$logname\/(.*)\/bin\/.*$

Replies are listed 'Best First'.
Re: Retrieve "ps -ef" strings using regex
by toolic (Bishop) on Aug 27, 2008 at 19:50 UTC
    I would change things such that you stuff the ps output into an array, rather than a single string:
    @outlines = `ps -ef | grep $logname`;

    Then, I would capture what you want with the regex, not the pre-match. Note that you can avoid excessive escaping in the regex by using alternate delimiters, m{}:

    use strict; use warnings; my $logname = 'mylogname'; while (<DATA>) { if (m{(.*/export/home/$logname)/.*/bin/.*}) { print $1, "\n" } } __DATA__ root 28834 28833 0 Aug25 ? 00:00:00 login -- mylogname2 root 29853 29852 0 Aug25 ? 00:00:00 login -- mylogname2 root 5379 5378 0 Aug26 ? 00:00:00 login -- mylogname2 root 5454 5453 0 Aug26 ? 00:00:00 login -- mylogname2 509 6710 1 0 00:20 ? 00:00:28 /export/home/mylogname/folder1/bin/binar +y 509 6729 1 0 00:35 ? 00:00:11 /export/home/mylogname/folder2/bin/binar +y 522 7996 1 0 07:00 ? 00:00:07 /export/home/mylogname2/folder1/bin/bina +ry 509 7997 1 0 07:00 ? 00:00:01 /export/home/mylogname/folder3/bin/binar +y 522 8045 1 0 07:02 ? 00:00:02 /export/home/mylogname2/folder4/bin/bina +ry

    prints:

    509 6710 1 0 00:20 ? 00:00:28 /export/home/mylogname 509 6729 1 0 00:35 ? 00:00:11 /export/home/mylogname 509 7997 1 0 07:00 ? 00:00:01 /export/home/mylogname

    Is this the output you are looking for?

    Update: Please re-read How do I compose an effective node title?.

      Thank a lot wise Monks.
      I finally figured it out before seeing your replies:

      my $logname = `logname`; chomp($logname); my @output = `ps -ef | grep $logname`; foreach(@output) { chomp; next if /\~$/ || !$_; my $file = $_; if ($file =~ /^.*\/export\/home\/$logname\/(.*)\/bin\/.*?/) { print "$1\n"; } }


      Displays what I want:
      folder1
      folder2
      folder3

      The soluce was indeed in the array instead of the string.
Re: Retrieve "ps -ef" strings using regex
by psini (Deacon) on Aug 27, 2008 at 19:42 UTC

    You are taking the full result of ps in a single string, checking if there is a match and then printing the entire string. This results in printing the entire result if there is at least a match.

    What you want to do is to split the string in an array of lines and then check & print each of them.

    Rule One: "Do not act incautiously when confronting a little bald wrinkly smiling man."

      instead of reading the result into a scalar and split it afterwards, you could assign the result of the backticks to an array.

      my @lines = qx{ command | grep what };
Re: Retrieve "ps -ef" strings using regex
by dwm042 (Priest) on Aug 27, 2008 at 20:11 UTC
    I agree with psini and toolic in terms of parsing 'ps -ef' but what I'd really like to suggest is that you investigate the 'o' option of ps. With ps -eo you can pull out things like the resident size of your application and the virtual memory size (i.e. how much RAM and how much virtual memory your program is using). The command ps -eo and a little parsing can be an effective diagnostic tool.

      Thanks for the tip!!
Re: Retrieve "ps -ef" strings using regex
by betterworld (Curate) on Aug 27, 2008 at 21:33 UTC

    Maybe you can get around that bothersome external-program stuff altogether. Have you considered Proc::ProcessTable?

      I was looking at the folder name holding the processes since I can have the same process name in different folder. I don't think the Proc::ProcessTable can answer my needs.
Re: Retrieve "ps -ef" strings using regex
by linuxer (Curate) on Aug 27, 2008 at 19:44 UTC

    you should print the captured string instead of $PREMATCH.

    # $PREMATCH
    # $`

    see perlvar (search for "PREMATCH") and perlretut (search for "Extracting matches")

    updated solution, the old one was insufficient:

    chomp( my $logname = qx{logname} ); my @output = qx{ps -ef | grep $logname}; for my $line ( @output ) { if ( $line =~ m{/export/home/$logname/(.+)/bin/} ) { print $1, "\n"; } }

    update1: edited perldoc hints

    update2: updated insufficient code; thanks psini for inspiration of array usage and jethro for pointing out my mistake in the previous code version

    update3: fixed typo in code