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

Preprocessing print statements

by mauroid (Initiate)
on Nov 11, 2020 at 10:26 UTC ( [id://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 (Saint) 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?Last hourOther CB clients
Other Users?
Others sharing their wisdom with the Monastery: (2)
As of 2024-04-26 00:37 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found