Howto Work with Record Separator in Perl
I have a data that looks like this
--
read50_1: read1391364_2,read3529226_1,
--
read46_2: read916_1,read开发者_JS百科178252_2,read1336397_1,read1824459_2,
read916_1: read0_1
--
read34_1: read209771_2,
--
read32_2: read520377_2,
What I want to do is to access the entry excluding the record separator "--".
But why this code doesn't do it?
my $INFILE_file_name = "myfile.txt"; # input file name
my $content = '';
open ( INFILE, '<', $INFILE_file_name )
or croak "$0 : failed to open input file $INFILE_file_name : $!\n";
{
local $/ = "--";
$content = <INFILE>;
print "$content\n";
}
close ( INFILE ); # close input file
First of all, I'm guessing you meant
local $/ = "--\n"; # or maybe "\n--\n"
(If you do use "\n--\n"
, then the first line will no longer be considered a record separator, but will be part of the first record. You might want to read that first --
line before changing $/
.)
Remember that $/
is not removed by the <IN>
operator. Use chomp
to do that.
Secondly, the file begins with the record separator, so the first record will be blank.
{
local $/ = "--\n";
while ($content = <INFILE>) {
chomp $content;
print "$content\n" if $content; # Skip empty records
}
}
You could also just do:
while(<INFILE>) {
print unless(/\s*--\s*/);
}
#!/usr/bin/env perl
use Modern::Perl;
use autodie;
use Data::Dump 'pp';
open my $file, "<", "input.txt";
{
local $/ = "--\n";
say pp <$file>;
}
close $file;
And the output:
(
"--\n",
"read50_1: read1391364_2,read3529226_1,\n--\n",
"read46_2: read916_1,read178252_2,read1336397_1,read1824459_2,\nread916_1: read0_1\n--\n",
"read34_1: read209771_2,\n--\n",
"read32_2: read520377_2,\n",
)
In other words, reading does not strip the input record separator. You might want something like this:
open my $file, "<", "input.txt";
{
local $/ = "--\n";
for (<$file>) {
chomp;
s/\n//g;
say "<$_>";
}
}
close $file;
Which gives:
<>
<read50_1: read1391364_2,read3529226_1,>
<read46_2: read916_1,read178252_2,read1336397_1,read1824459_2,read916_1: read0_1>
<read34_1: read209771_2,>
<read32_2: read520377_2,>
As a side note, you should use the three-arg open and you might be interested in autodie so that you won’t have to write the or die
boilerplate.
While using the record separator here is a possibility, it's not a very good solution unless the '--'s imply some meaningful grouping of data (that will be used). If the purpose is to merely filter out the '--'s, use loop control.
use strict;
use warnings;
my $file = 'myFile.txt';
open my $fh, '<', $file or die "Unable to open $file: $!";
while ( <$fh> ) { # Read text file line-by-line
next if /^--/; # Skips current line if it begins with '--'
print; # Will only execute if line doesn't begin with '--'
}
close $fh;
Try this:
my $INFILE_file_name = "myfile.txt";
my @content = ( );
open ( INFILE, '<', $INFILE_file_name );
@content = <INFILE>;
close ( INFILE );
foreach my $line (@content) {
$line =~ s/^\s+//;
$line =~ s/\s+$//;
if ($line eq '--') {
next;
}
print $line . "\n";
}
From that, you would be able to access the records line by line, without the --
separator. Also, if you want to just put it in one variable instead of an array, you can just:
$file .= $line . "\n";
local $/="--\n"; while(chomp($_=)){print;}
$content = <INFILE>
fetches only the next line which ends with the characters in $/
. It should be wrapped in a loop to get all the lines.
while ( $content = <INFILE> ) {
chomp $content;
print "$content\n";
}
Modern Perl users stay away from bareword filehandles. Instead, use lexical variables as filehandles. To know why lexical variables are preferred to bareword filehandles, read: Bareword uppercase filehandles.
精彩评论