How can I avoid Perl :: Critic warnings when processing a multi-line string with a file descriptor?

Does anyone have a solution to the problem of handling a multi-line string one line at a time other than the below string-as-a-file solution?

my $multiline_string = "line one\nline two\nline three\nline four";
my $filehandle;
open( $filehandle, '<', \$multiline_string )
    or croak("Can't open multi-line string as a filehandle: $!");
while ( defined (my $single_line = <$filehandle>) ) {
    # do some processing of $single_line here ...
}
close( $filehandle );

      

My reason for not using a file descriptor is pretty weak. Test :: Perl :: Critical screams when I have more than 10 lines of source code between my open command and my close command on any file descriptor. I'm doing quite a lot of $ single_line processing, so I actually have about 40 lines of code between my open call and my closed call, and I don't see any way to get that to 10.

And I really don't want to ignore the Perl :: Critic test in my assembly, because it is a really decent test that I would like to pass whenever I open an actual file on disk in my code.

+2


source to share


8 answers


Make Creta Perl happy and make yourself even happier by creating a subroutine and name it with every line of the file.



use strict; use warnings;

sub do_something {
    my ($line) = @_;
    # do something with $line
}

open my $fh, '<', \$multiline_string
    or die "Cannot open scalar for reading: $!";

while(<$fh>) {
    chomp;
    do_something($_);
}

close $fh; 

      

+9


source


Um, isn't the purpose of boredom to make you have smaller blocks of code that only do one thing? make a subroutine that does what is needed for each line.



Many people have suggested split /\n/

. split /^/

looks more like the filehandle path.

+5


source


What about:

my $multiline_string = "line one\nline two\nline three\nline four";
my @lines = split(/\n/,$multiline_string);
foreach my $line (@lines) {
    #do stuff with string
}

      

+3


source


I may be missing something, but you could do:

my @lines = split(/\n/,$multiline_string);
foreach my $single_line (@lines) {
  ...
}

      

+3


source


Long before I even knew that you could flip a multiline string into a file descriptor, there was split

:

foreach my $single_line (split /\n/, $multiline_string) {
    # process $single_line here
    # although note that it doesn't end in a newline anymore
}

      

Insert a statement about using literal and non-portable \n

here.

+3


source


Perl :: Critic is nice, but when you start obsessing with some of its requirements, it starts wasting its time, not saving it. I just let the file descriptor go out of scope and not worry about being closed:

 my $multiline_string = "line one\nline two\nline three\nline four";

 {
     open my( $fh ), '<', \$multiline_string )
         or croak("Can't open multi-line string as a filehandle: $!");
     while ( defined (my $single_line = <$fh>) ) {
         # do some processing of $single_line here ...
     }
 }

      

A lot of people achieve regex or break, but I think this is sloppy. You don't need to create a new list and use much more memory in your program.

+2


source


You can use regular expression.

#!/usr/bin/perl

use strict;
use warnings;

my $s = "line one\nline two\nline three\nline four";

while ($s =~ m'^(.*)$'gm) {
    print "'$1'\n";
}

die "Exited loop too early\n" unless pos $s == length $s;

      

Or you can use split

:

for my $line ( split m'\n', $multiline_string ){

  # ...

}

      

0


source


Personally, I like to use it $/

to split strings in a multi-line string.

my $multiline_string = "line one\nline two\nline three\nline four";
foreach (split($/, $mutliline_string)) {
  process_file($_);
}
sub process_file {
  my $filename = shift;
  my $filehandle;
  open( $filehandle, '<', $filename )
      or croak("Can't open multi-line string as a filehandle: $!");
  while ( defined (my $single_line = <$filehandle>) ) {
      process_line($single_line);
  }
  close( $filehandle );
}
sub process_line {
  my $line = shift;
  ...
}

      

-1


source







All Articles