in reply to Handling multiple output files simultaneously using arrays of filehandles and filenames

The other part of this is that when you use a file handle that is an array or hash element, you must IIRC use the syntax
    print { $fh[5] } "something \n";
(note the curly braces around the file handle that form a scope).

I'd like to provide a doc link, but I can't offhand remember where this is discussed. I may be able to look this up later, but in the meantime perhaps another monk may fill the gap. :)


Give a man a fish:  <%-{-{-{-<

  • Comment on Re: Handling multiple output files simultaneously using arrays of filehandles and filenames
  • Select or Download Code

Replies are listed 'Best First'.
Re^2: Handling multiple output files simultaneously using arrays of filehandles and filenames
by pryrt (Monsignor) on Jan 21, 2021 at 18:33 UTC
    I'd like to provide a doc link

    print

    If you're storing handles in an array or hash, or in general whenever you're using any expression more complex than a bareword handle or a plain, unsubscripted scalar variable to retrieve it, you will have to use a block returning the filehandle value instead, in which case the LIST may not be omitted
      Thanks for that reference. I had indeed read that document earlier today but suddenly felt drained of all energy when I read the phrase "bareword handle" which meant nothing to me. I must learn more. I must learn more. I must learn more. Thrash. Whip. I am a member of Opus Doh. :-D
Re^2: Handling multiple output files simultaneously using arrays of filehandles and filenames
by eyepopslikeamosquito (Bishop) on Jan 22, 2021 at 01:09 UTC

    A stylistic advice reference is Perl Best Practices, Chapter 10 (I/O), Item 136: Always put filehandles in braces within any print statement:

    It's easy to lose a lexical filehandle that's being used in the argument list of a print:

    print $file $name, $rank, $serial_num, "\n";

    Putting braces around the filehandle helps it stand out clearly:

    print {$file} $name, $rank, $serial_num, "\n";
    The braces also convey your intentions regarding that variable; namely that you really did mean it to be treated as a filehandle, and just didn't forget a comma.

    An alternative syntax using IO::Handle:

    use IO::Handle; $file->print( $name, $rank, $serial_num, "\n" );

Re^2: Handling multiple output files simultaneously using arrays of filehandles and filenames
by Cosmic37 (Acolyte) on Jan 21, 2021 at 20:56 UTC
    Thanks - you are right that I want to open these files in order that I will under some logical conditions write a data line to them. One of my data items per line is indeed a $sector value and I will breakd down the data by $sector, outputting each line of input to the relevant output file per sector. My thinking was to use the following but it looks like you are advising me to insert curly braces which I will try although I don't really understand why this would make a difference and why print would have a problem sending a string to a file handler without curly braces...
    $mydata=<INPUT>; while(<INPUT>){ #Handle data file line by line splitting it at every new line \n my(@data)=split/\n/,$_; #Now lets go through the whole input data file line by line for($i=0;$i<@data;$i++){ $mydata=$data[$i]; if($mydata=~/^Blah$some_regex(\d+)$some_more_regex_perhaps/){ #Get the sector value which is listed in each matching line of data $DataSector=$1; #Output line of matching data to output file for the relevant sector print $fh[$dataSector] "$mydata\n"; } }
      > why print would have a problem sending a string to a file handler without curly braces

      You are conflating two levels: parsing of the source code and execution. When executed, print has no problem to send a string to a file handler, but there aren't any curlies anymore. The problem is the parser first needs to find out what and where to you want to print. And Perl parser is very simple and can never look ahead more than one token. Therefore, it can't check whether there's a comma after the $fh[$dataSector], because it only sees $fh and the next token is the index.

      map{substr$_->[0],$_->[1]||0,1}[\*||{},3],[[]],[ref qr-1,-,-1],[{}],[sub{}^*ARGV,3]
      ... #Output line of matching data to output file for the relevant sector print $fh[$dataSector] "$mydata\n"; ...

      So the syntax you need to use is
          print { $fh[$dataSector] } "$mydata\n";
      (extra spacing around the curlies just for visibility/clarity).


      Give a man a fish:  <%-{-{-{-<

        Thanks again. I would like to confirm to you that this is indeed what I have done. Using curly braces allowed successful execution of the code. I also tried without the curly braces as a cross check of your correctness and I can confirm that the code failed in that case. Therefore I can confirm that on this occasion your advice was top notch! Spitze! Ausgezeichnet! Parfait! Fabuloso! Wunderbra!