-1

I have an array of entries which will be search in a large file, each entry is then written to its own output file. the array varies based on certain conditions and therefore has to be dynamic.

Here is my example array.

use strict;
use warnings;

my @array = ("ABC",
             "DEF",
             "GHI",
             "JKL",
             "MNO",
             "PQR"
             );

So I created a loop to open create a filehandle for each of the entries. run my commands, then a loop again to close the filehandles.

foreach my $handle(@array) {
        my $output = "OUTPUT_$handle.txt";
           open ($handle, '>', $output) or die "unable to open file $!";
}

#... write to files and do some other fancy stuff ...

foreach $handle(@array) {
           close $handle;
    }

Which will create: OUTPUT_ABC.txt OUTPUT_DEF.txt.. etc.

So my question: It seems to feel very awkward for me to have to loop through opening each and loop closing each handle, is there a more elegant method to open and close file handles dynamically?

Gerhard
  • 22,678
  • 7
  • 27
  • 43

2 Answers2

0

You could use lexical filehandles:

use strict;
use warnings;

my @array = qw/ABC DEF/;

{
    my %fh = map { open my $fh, ">", "OUTPUT_$_.txt"; $_ => $fh } @array;
    print {$fh{ABC}} "Something...";
}
# Here your filehandles in %fh will be closed already.
brian d foy
  • 129,424
  • 31
  • 207
  • 592
-1

I don't understand your concern, but you could make it more concise by using statement modifiers. Also, using the autodie pragma removes the need to check the status of each operation

use autodie;

open $_, '>', "OUTPUT_$_.txt" for @array;

...

close for @array;

Note that, if you wrap the code that uses the file handles in @array in a block { ... }, then they will be closed implicitly when they go out of scope. You just need to make sure that the declaration my @array (a terrible identifier, by the way) is within the block.

Gerhard
  • 22,678
  • 7
  • 27
  • 43
Borodin
  • 126,100
  • 9
  • 70
  • 144
  • It is not so much a concern, might just be my OCD. This is what I meant with more elegant. Thank you – Gerhard Feb 15 '18 at 13:51
  • Are those lexical filehandles or old-style handles? Because `@array` is an array of strings, not file handles so my gut feeling is that those won't close when they go out of scope. – el.pescado - нет войне Feb 15 '18 at 14:17
  • 1
    @el.pescado: They use lexical array elements, so they are lexical handles. The original contents of the array are irrelevant except for building the file name string. The call to `open` overwrites each array element with the new file handle reference. – Borodin Feb 15 '18 at 14:35
  • @Borodin Are you sure? `print Dumper \@array;` indicates otherwise. `system("ls -l /proc/$$/fd");` shows that files are still open. – el.pescado - нет войне Feb 15 '18 at 14:58
  • OK, found it. *"If FILEHANDLE is an **undefined** scalar variable (or array or hash element), a new filehandle is autovivified, meaning that the variable is assigned a reference to a newly allocated anonymous filehandle. Otherwise if FILEHANDLE is an expression, its value is the real filehandle. (This is considered a symbolic reference, so use strict "refs" should not be in effect.)"*. [(perldoc open)](http://perldoc.perl.org/functions/open.html) So that passing lexical value to `open` is not sufficient - it has to be undefined. This code opens `ABC`, `DEF` etc old-style file handles. – el.pescado - нет войне Feb 15 '18 at 15:03