Beefy Boxes and Bandwidth Generously Provided by pair Networks
Keep It Simple, Stupid
 
PerlMonks  

Effective way in perl

by RajNaidu (Novice)
on Jul 16, 2009 at 05:15 UTC ( [id://780556]=perlquestion: print w/replies, xml ) Need Help??

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

Hi Perl Monks, I have the below commands in my perl script, which is actually a repetation of single statement but outputting to different logfiles. `echo "$swlist -l depot @ $depot_locn | $grep $rel_string | $grep $i +| $grep AR" >> $log_std_depot`; `$swlist -l depot @ $depot_locn | $grep $rel_string | $grep $i | $grep + AR >> $log_std_depot`; `$swlist -l depot @ $depot_locn | $grep $rel_string | $grep $i | $grep + AR >> $temp_log`; Is there any way I can make my code more effective in perl. Please adv +ise.

Replies are listed 'Best First'.
Re: Effective way in perl
by CountZero (Bishop) on Jul 16, 2009 at 06:00 UTC
    What problems do you have with this code? Is it slow, uses too many resources, ...? "Effective" is a word with many meanings.

    Did you take a look at the various Logging-modules on CPAN?

    CountZero

    A program should be light and agile, its subroutines connected like a string of pearls. The spirit and intent of the program should be retained throughout. There should be neither too little or too much, neither needless loops nor useless variables, neither lack of structure nor overwhelming rigidity." - The Tao of Programming, 4.1 - Geoffrey James

      Hi, My code has repetation of same lines i.e execution of same command output has been redirected to two separate log files. Is there any way, I can use reduce the number of lines of the program in perl. Please advise.
Re: Effective way in perl
by cdarke (Prior) on Jul 16, 2009 at 08:00 UTC
    Use a subroutine for the common code, passing in the variable parts are parameters. However, these lines are not that similar. The first one does an echo and the others call $swlist as a program.

    To make the code more effective in perl you can easily replace the grep program by a perl regular expression (make sure you are using Extended RE constructs in the regular expressions - grep uses Basic REs which differ slightly). You can run the $swlist program in a pipe to grab the output one line at a time, see open.
Re: Effective way in perl
by graff (Chancellor) on Jul 16, 2009 at 13:15 UTC
    You seem to be running the same command two times, just to have its output stored in two distinct output files. Apart from that, I'd be worried about the risks of running shell commands that way, unless there is very hight certainty that the perl variables being used to build the command are "safe" (contain no shell metacharacters, etc).

    In any case, it seems like you only need a shell to run the initial part of your pipeline, and it would be just as well for perl to do the rest:

    my @command = ( $swlist, '-l', 'depot', '@', $depot_locn ); my $child_pid = open( my $shell, '-|', @command ) or die "shell command failed: $!\n"; open( my $out1, ">>", $log_std_depot ) or die "$log_std_depot: $!\n"; open( my $out2, ">>", $temp_log ) or die "$temp_log: $!\n"; print $out1 "COMMAND: @command ## FILTERS: $rel_string / $i / AR\n"; while (<$shell>) { next unless ( /$rel_string/ and /$i/ and /AR/ ); print $out1 $_; print $out2 $_; } close $out1; close $out2; close $shell;

    Update: note that by doing the "grep" parts inside perl, you are able to make use of perl's much more powerful regex syntax -- you can do things that would not be possible with the standard command-line grep tool.

    Another update: changed the code snippet to open the two output file in append mode (>> as per the OP code) rather than "truncate" mode.

      Hi Graff , Thanks for the suggestions. I tried running your code inside perl script. When i execute the above code , I see only below lines in the log file. (log_std_depot) COMMAND: /usr/sbin/swlist -l depot @ sidedepot.fc.com ## FILTERS: 0909 / / AR And also $temp_log seem to be empty. The commands are not getting executed, it only outputs the above line in the logfile. Are we missing anything here.
        The fact that your "log_std_depot" log file is showing two slashes in a row indicates that you are not setting $i. Apart from that, if you take the command line string from that log file ("/usr/sbin/swlist -l depot @ sidedepot.fc.com") and run it manually in a shell, what happens?

        If you make changes in the command string in order to get it to work in the shell, just make sure you apply the same changes in the perl script.

Re: Effective way in perl
by rovf (Priest) on Jul 16, 2009 at 08:24 UTC
    I guess $grep expands to the grep of your choice, and since you are redirecting the stdout, your expression is supposed to return only the stderr of the programs. Is this correct?

    I don't find your code so bad (since I, personally, wouldn't care about all the grep processes you are spawning). If you wouldn't insist on separating $swlist's stdout and stderr, you could open(SWLIST,'/your/swlist|') and grep inside your Perl program. If you need to keep stdout and stderr apart, have a look at IPC::Run.

    -- 
    Ronald Fischer <ynnor@mm.st>
Re: Effective way in perl
by JavaFan (Canon) on Jul 16, 2009 at 11:42 UTC
    Assuming that $swlist constains a command having to do with HP's package system, I don't see much improvement. You'll have to spawn seperate processes anyway, and the grep utility is pretty fast.

    However, it seems you are doing the same command twice, sending the resulting output to two different files; you could send the output to a (temp) file once, and then concat the output to both $log_std_depot and $temp_log.

    And if you aren't using the output of the pipe chain (which wouldn't make sense, as you're sending that to the files anyway), you might prefer system over backticks.

Re: Effective way in perl
by QM (Parson) on Jul 16, 2009 at 16:03 UTC
    Unix tee has always done the job for me. Do you need to append?

    Update: added link.

    -QM
    --
    Quantum Mechanics: The dreams stuff is made of

      I basically need to reduce my two-liner code to single line coz I will be handling similar situations in my remaining code. If I have repetation lines doing the same job , my code length will be too huge. How do I use unix tee in perl script, please advise
        You have:
        `$swlist -l depot @ $depot_locn | $grep $rel_string | $grep $i | $grep + AR >> blah`

        which isn't pure perl code anyway, is it? (It's convenient to call grep 3 times, but might be more efficient to do with Perl's own grep.) Here, you're using perl just like you would use sh.

        But to address your question, try:

        `$swlist -l depot @ $depot_locn | $grep $rel_string | $grep $i | $grep + AR | tee file1 | tee file2 | tee file3 >> tee file4`
        But if you need append, I don't think tee can do that.

        Also take a look at Regexp Quote Like Operators and What's wrong with using backticks in a void context?

        -QM
        --
        Quantum Mechanics: The dreams stuff is made of

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://780556]
Approved by rovf
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others avoiding work at the Monastery: (4)
As of 2024-04-19 13:37 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found