Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl: the Markov chain saw
 
PerlMonks  

Dereference a reference to a file handle created with IO::File

by dgdriscoll (Initiate)
on Oct 28, 2020 at 01:32 UTC ( #11123242=perlquestion: print w/replies, xml ) Need Help??

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

Hi, everything else seems to work if I manually insert file names instead of using hash values but everything I have tried on lines 40,44 &47 gives me a string instead of a file handle. What am I doing wrong? thanks, Dave Driscoll

#!/usr/bin/perl -w #ad_sort.pl #in ~/logs take paydirt.log as input #for each item in the ads hash, #search for a match for 'GET /bookstore/'+ads key #when a match is found, write that and all following lines to #ads key value . #until a string containing '####' is found then stop writing #keep reading until next match or EOF use IO::File; use strict; use diagnostics; my $do_write = 'no'; open(MYINPUTFILE, "<paydirt.log") || die("$!"); my $western_lore_ad1 = IO::File->new("> ad_logs/western_lore_ad1.log") +; my $western_lore_ad2 = IO::File->new("> ad_logs/western_lore_ad2.log") +; my $western_lore_ad3 = IO::File->new("> ad_logs/western_lore_ad3.log") +; my $native_ad1 = IO::File->new("> ad_logs/native_ad1.log"); my $native_ad2 = IO::File->new("> ad_logs/native_ad2.log"); my %ads = ('western_lore.php?ad=n1'=>$western_lore_ad1,'western_lore.p +hp?ad=n2'=>$western_lore_ad2,'$western_lore.php?ad=n3'=>$western_lore +_ad3,'native.php?ad=n1'=>$native_ad1,'native.php?ad=n2'=>$native_ad2) +; my @ad_strings = keys $ads; my(@lines) = <MYINPUTFILE>; foreach (@ad_strings){ my $this_ad = $_; my $clicks = 0; foreach my $line (@lines){ if ($line =~ m/GET \/bookstore\/\Q$this_ad/){ $do_write = 'yes'; $clicks++; } if ($do_write eq 'yes'and $line =~ m/###/){ print $ads{$this_ad} "$line\n";#this should print to one of the +files referenced by IO::File on lines 21-25 $do_write = 'no'; } if($do_write eq 'yes' ){ print $ads{$this_ad} $line;#ditto } } print $ads{$this_ad} "clicks = $clicks \n";#ditto } close (MYINPUTFILE); $western_lore_ad1->close; $western_lore_ad2->close; $western_lore_ad3->close; $native_ad1->close; $native_ad2->close; exit ();

Replies are listed 'Best First'.
Re: Dereference a reference to a file handle created with IO::File
by Fletch (Chancellor) on Oct 28, 2020 at 02:08 UTC

    Not 100% sure this is your issue but if you use anything in the indirect object / filehandle argument "slot" to print other than a simple scalar variable (edit: or a plain bareword, of course) you're going to need to wrap it in a block like print { $ads{ $this_ad} } "blah blah";. I'm surprised that it's even parsing and not throwing a syntax error the way you've got it now (samples w/5.32.0 on OS X).

    $ perl -MO=Deparse,-p,-q -E 'print $ads{$this_ad} "$line\n";' String found where operator expected at -e line 1, near "} "$line\n"" (Missing operator before "$line\n"?) syntax error at -e line 1, near "} "$line\n"" -e had compilation errors. $ perl -MO=Deparse,-p,-q -E 'print { $ads{$this_ad} } "$line\n";' use feature 'current_sub', 'bitwise', 'evalbytes', 'fc', 'postderef_qq +', 'say', 'state', 'switch', 'unicode_strings', 'unicode_eval'; print({$ads{$this_ad};} ($line . "\n")); -e syntax OK

    Afterthought: you also could call the print method on your handle as an alternative: $ads{$this_ad}->print( "blah" )

    The cake is a lie.
    The cake is a lie.
    The cake is a lie.

      Thank you very much. I chose your second suggestion, calling a method on the handle as being both shorter and, to me at least, clearer. There is something about nested {}'s when the inner and outer set do different things that is challenging for someone who gets into Perl once every couple of years or so. If there is any performance differential, it won't matter in my case. Thanks again, Dave Driscoll

Re: Dereference a reference to a file handle created with IO::File
by BillKSmith (Prior) on Oct 28, 2020 at 02:17 UTC
    Refer print:
    FILEHANDLE may be a scalar variable containing the name of or a reference to the filehandle,...

    UPDATE: Changed emphasis per Tobyink (below)

    Bill

      Yeah, this is a place you need to pay careful attention to the wording. It has to be a scalar variable, not just a scalar.

      Like foo() could return a scalar, and that scalar could be a reference to a filehandle. But print foo() "string\n" will fail because even though foo() evaluates to a scalar, it's not a scalar variable. Nor is $foo{'somekey'}.

      Same as you're not allowed to do:

      my %foo; for $foo{'somekey'} ( @arr ) { ...; }
Re: Dereference a reference to a file handle created with IO::File
by ikegami (Pope) on Oct 30, 2020 at 12:36 UTC

    print can be used as follows:

    print $SCALAR LIST print $SCALAR print BLOCK LIST print BLOCK print LIST print

    You have the following:

    print $ads{$this_ad} "$line\n";

    $ads{$this_ad} doesn't match $SCALAR or BLOCK, so this must be print LIST. But that's not what you want. Replace what you have with

    print { $ads{$this_ad} } "$line\n";
    or
    $ads{$this_ad}->print("$line\n");

Log In?
Username:
Password:

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

How do I use this? | Other CB clients
Other Users?
Others scrutinizing the Monastery: (3)
As of 2020-12-01 06:34 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found

    Notices?