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

Background: I am writing a subroutine which will be given a bunch of process descriptions like "cmdline=/usr/bin/apache" or "cmdline=/usr/bin/emacs /etc/passwd" or "rss>123456". (Probably packaged in a hash).

It should use Proc::ProcessTable to look at each process in turn, and return all the data it has on the processes that match each description.

The problem is, Proc:ProcessTable returns an object, where every property of a process is an accessor method for that object.

Obviously, I can't do $p->$key==$val, much as that would come in handy right now.

I think that I need to either do something ugly with eval, or create a chain of ifs like if ($key eq 'cmdline') {$match=$p->cmdline} elsif ($key eq... etc.

The matter is made more complicated because I have to return data about the process in a hash - I'm not allowed to just return a Proc::ProcessTable::Process object. That means that even if I use a series of ifs in the matching part, I still need a solution for the reporting part.

I was thinking of dispensing with Proc::ProcessTable altogether and just parsing the output of ps, but this code needs to run as transparently as possible on at least Linux and Solaris...

Replies are listed 'Best First'.
Re: $var as accessor name?
by broquaint (Abbot) on Mar 11, 2004 at 15:04 UTC
    You could always just extend Proc::ProcessTable e.g
    sub match { my($self, @matches) = @_; my @fields = $self->fields; my @ret; for my $p (@{ $self->table }) { push @ret => { map {; $_ => $p->$_ } @fields } if grep { my $val = $_; grep { $p->$_ =~ $val } @fields } @matches; } return @ret; }
    That will return a list of hashes, each containing the information for each process where one of the fields matched one of the match values.
    HTH

    _________
    broquaint

      Thank you, everybody, for pointing out my blind spot.

      I guess when you're wondering if Perl can do something, you should try it first, because usualy it does :-)

      Special thanks to broquaint for this lovely code.

        If the method name is a variable, it does have to be a simple scalar (e.g. $obj->$hash{method_foo} won't work).
Re: $var as accessor name?
by dragonchild (Archbishop) on Mar 11, 2004 at 14:50 UTC
    You most definitely can use a variable as a method name. Your issue is you cannot use methods as lvalues (unless they have the lvalue attribute), which is different. (Only read =, not == ... LASIK must be fading)
    package Foo; sub foo { print "Foo\n"; } sub bar { print "Bar\n"; } sub new { bless {}, shift } package main; my $foo = Foo->new; foreach my $method (qw( foo bar )) { $foo->$method; }
    (The above code has been tested on Perl 5.8.0/Solaris9)

    ------
    We are the carpenters and bricklayers of the Information Age.

    Please remember that I'm crufty and crochety. All opinions are purely mine and all code is untested, unless otherwise specified.

      With regard to $foo->$method, I believe that in some earlier versions (5.005?), the parenthesis are not optional:

      $foo->$method();

      Also with regard to $foo->$method = $value, note that because Proc::ProcessTable::Process doesn't use lvalue accessors, you need to pass the value as an argument:

      $foo->$method( $value );
Re: $var as accessor name?
by Fletch (Bishop) on Mar 11, 2004 at 14:53 UTC
    Obviously, I can't do $p->$key==$val, much as that would come in handy right now.
    $ perl -le 'sub a { "x" } sub b { "y" }; $p = bless {}; for $key ( qw( + a b ) ) { print $p->$key() }' x y

    Yes, you obviously can't do that.

Re: $var as accessor name?
by Juerd (Abbot) on Mar 11, 2004 at 14:49 UTC

    Obviously, I can't do $p->$key==$val

    And why is that?

    Juerd # { site => 'juerd.nl', plp_site => 'plp.juerd.nl', do_not_use => 'spamtrap' }