Beefy Boxes and Bandwidth Generously Provided by pair Networks
Problems? Is your data what you think it is?
 
PerlMonks  

Preprocessing print statements

by mauroid (Initiate)
on Nov 11, 2020 at 10:26 UTC ( #11123579=perlquestion: print w/replies, xml ) Need Help??

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

I have a long script that uses print (to STDOUT) in various places to print data to a terminal. Now I need to add a 'grep' option within the script so that only lines that match a certain regular expression are printed; all the rest are not printed.

I would be OK with adding a new FILEHANDLE in front of every print statement, but I would want to avoid calling my own print subroutine every time I want to do a print. So something like this would be OK (only the first line should be printed in STDOUT, the second would not be printed):

my $GREP_STR = "123"; ## a global var print GREP_FH "My line with 123\n"; ## anywhere in the code print GREP_FH "My line with 456\n";

but not this

&myprint("My line with 123\n"); &myprint("My line with 456\n");

Ideally I would also want the ability to print lines that override the 'grep' and are printed anyway, but that's optional. So something like this:

$GREP_STR = '123'; print STDOUT "Header - always print this\n"; print GREP_FH "My line with 123\n"; ## printed at the terminal print GREP_FH "My line with 456\n"; ## not printed

I thought that by using 'select' I could auto-redirect the STDOUT to maybe a subroutine, and then decide there if I want to print something or not, but it seems like 'select' only redirects to an actual FILEHANDLE and can't redirect to a subroutine.

Replies are listed 'Best First'.
Re: Preprocessing print statements
by Corion (Patriarch) on Nov 11, 2020 at 10:41 UTC

    Your idea of "auto-redirect"ing a filehandle to a subroutine is possible using a tie'd filehandle (see Tying FileHandles). This is not a sane solution for a long-term approach, but for the short term it will work:

    package GreppedFileHandle; use strict; sub TIEHANDLE { local *FH; open my $self, \*FH; bless $self, shift } sub PRINT { my $self = shift; my $output = "@_"; if( $output =~ /\Q$::GREP_STR\E/ ) { print( STDOUT $output ); } else { print "Swallowed a line\n"; }; } package main; our $GREP_STR = '123'; # needs to be 'our', not 'my' tie *grep_fh, 'GreppedFileHandle'; print STDOUT "Header - always print this\n"; print grep_fh "My line with 123\n"; ## printed at the terminal print grep_fh "My line with 456\n"; ## not printed

    For the long term approach, you should look at a logger framework (like Log::Log4perl) or a "simple" logging subroutine like your &myprint() to centralize the logging.

      This works perfectly! Thank you so much!

Re: Preprocessing print statements
by LanX (Sage) on Nov 11, 2020 at 12:19 UTC
    two alternative approaches:

    a) If you are OK with buffering, you can still use select with a filehandle opened to a \$scalar and filter the scalar before printing. This has the advantage of minimal changes.

    b) Personally I'd prefer my own out() routine - closing over a regex var - to replace all needed prints. That'll give you finer control over the single print chunks.

    HTH

    Cheers Rolf
    (addicted to the Perl Programming Language :)
    Wikisyntax for the Monastery

    UPDATED: Clarified that these are two different approaches.

      Thank you. Could you please provide a sample code snippet? I am not entirely clear how to do what you suggest.

Re: Preprocessing print statements
by salva (Canon) on Nov 12, 2020 at 09:27 UTC
    You can fork a new process for doing the filtering in parallel:
    use POSIX; ... my $pid = open(STDOUT, "|-") // die "unable to fork new process"; unless ($pid) { while (<>) { print if /the-regular-expression-goes-here/ } POSIX::_exit(0); } # after this point, STDOUT is filtered

    Update: That works in Unix/Linux systems. I am not sure about Windows, but probably not!

Log In?
Username:
Password:

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

How do I use this? | Other CB clients
Other Users?
Others studying the Monastery: (4)
As of 2022-05-20 22:55 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    Do you prefer to work remotely?



    Results (76 votes). Check out past polls.

    Notices?