Beefy Boxes and Bandwidth Generously Provided by pair Networks
more useful options

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
[choroba]: What about [metadoc:// Algorithm::Loops]?
[Corion]: choroba: Yeah, but handing off the request to Dancer,Plack, Mojolicious,LWP is easy once I have the data filled into some structure ;))
[choroba]: Algorithm::Loops
[Corion]: choroba: I'm using that to generate the permutations, but I don't know how the user can pass the intended values to my function in a sane way
[Corion]: I have a prototype that permutes the get_parameters, but the values used for the get parameters should be different from the values used for the headers and potentially for parts of the URL
[Corion]: But yes, in general, my approach will be "split the URL into another set of parameters, generate an array of allowed values for each parameter and then NestedLoops() over the set"
[choroba]: hmm... so you need something like bag from Test::Deep, but not for checking, but for generation
[Corion]: This has the dual use of easily requesting sequential URLs and also being suitable for testing
[Corion]: For testing, I want to skip all tests with the same value(s) once one test fails to cut down on the number of failing tests
[Corion]: choroba: Yes, in a way I

How do I use this? | Other CB clients
Other Users?
Others romping around the Monastery: (5)
As of 2017-01-17 08:20 GMT
Find Nodes?
    Voting Booth?
    Do you watch meteor showers?

    Results (152 votes). Check out past polls.