Beefy Boxes and Bandwidth Generously Provided by pair Networks
There's more than one way to do things

spaces in grep command argument executed in backticks

by chilukuri_perl (Novice)
on Oct 22, 2009 at 05:52 UTC ( #802648=perlquestion: print w/replies, xml ) Need Help??
chilukuri_perl has asked for the wisdom of the Perl Monks concerning the following question:

$module variable contains white spaces which are interprested by shell and giving the errors
$module = "xyz abc"; $pid = `ps -aef|grep "$module"|grep -v grep |cut -d ' ' -f3`; grep: can't open xyz grep: can't open abc
How can shell interpretation of white spaces can be avoided for above prupose

Replies are listed 'Best First'.
Re: spaces in grep command argument executed in backticks
by jwkrahn (Monsignor) on Oct 22, 2009 at 06:23 UTC
    my $module = 'xyz abc'; open my $PIPE, '-|', 'ps', '-aef' or die "Cannot open pipe from 'ps' $ +!"; my $pid; while ( <$PIPE> ) { next unless /$module/; $pid = ( split )[ 2 ]; } close $PIPE or warn $! ? "Error closing 'ps' pipe: $!" : "Exit status $? from 'ps'";
Re: spaces in grep command argument executed in backticks
by cdarke (Prior) on Oct 22, 2009 at 08:03 UTC
    The third field of ps -ef is the parent pid, did you mean that? Also, you can avoid the extra grep -v with a simple RE trick:
    $module = "xyz ab[c]"; $pid = `ps -aef|grep \"$module\"|cut -d ' ' -f3`;
    Note the [ ] around one of the characters.

    Back to perl, here is a simple one-liner (OK, three lines) which only creates one child process:
    my $module = 'xyz abc'; my @ppids = map {(split)[2]} grep /$module/,`ps -ef`; print "@ppids\n";
    If you really wanted the pid rather than the ppid then change the [2] to [1].
    Notice that I am using an array, since there might be more than one process which matches.
      my @ppids = map {(split)[2]} grep /$module/,`ps -ef`;
      my @ppids = map /$module/?(split)[2]:(), `ps -ef`;
Re: spaces in grep command argument executed in backticks
by jakobi (Pilgrim) on Oct 22, 2009 at 07:33 UTC

    For a general solution surviving not just embedded blanks, check the recent thread on use variables of system and my reply on secure use here.</p.

    Then again, you can just move the grep to perl, which takes also care of the issue and allows more powerful regexes. A perl -e "one-liner" example would be e.g.

    perl -e '$module=$ARGV[0]; @ps=`ps -eaf`; shift @ps if $ps[0]=~/^UID|^USER/; @ps=grep {/$module/} @ps; $pid=+(split / +/, $ps[0])[1]; warn "pid: $pid"; warn "multiple matches" if $#ps>0; warn @ps' urxvt

    Wasn't there a module to abstract from or at least parse ps: the ps output if rather inconsistent when comparing e.g. BSD vs SYSV vs GNU...? Just consider the PID field, which for me is the 2nd field.

    Update: stripped the and not /grep/ from the grep, claiming shell muscle memory - ps and a lone grep in one line just feel wrong. @jwkrahn thanx for spotting it!

      @ps=grep {/$module/ and not /grep/} @ps;

      Why would you try to match the string /grep/ when you are using Perl's grep function.    That makes no sense at all.

Re: spaces in grep command argument executed in backticks
by Anonymous Monk on Oct 22, 2009 at 06:12 UTC

    use single quotes

    grep \'$module\'

    or alternatively use

    $module ="'xyz abc'"

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://802648]
Approved by GrandFather
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others meditating upon the Monastery: (4)
As of 2017-06-25 18:03 GMT
Find Nodes?
    Voting Booth?
    How many monitors do you use while coding?

    Results (568 votes). Check out past polls.