开发者

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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜