简体   繁体   中英

How can I read multiple lines in Perl?

I just want to read multiple lines in a file. For example in sample.txt

"Hi, how are you?"
"Hello 

I'm
fine, thank you!"

Now my problem is how can I read the second statement without removing the newline in the sentence?

EDIT:

It seems that my questions are not clear. So I think I should edit this: In my examples above, I need to get the whole,

"Hello 

I'm
fine, thank you!"
while ($line = <PFILE>)
{
   #How can I get the statement to $line?
}

If you want to read all lines at once, change the line-separator $/ :

{
    local $/;  # change the line separator to undef
    $filecontents = <FILE>;
}

if you want to read two lines at a time you can just read two lines at a time.

$lines1_and_2 = <FILE>;
$lines1_and_2 .= <FILE>;

I'm not sure what you mean by 'without removing the newline' in the sentence, but to read a file, line by line, you would do something like

open MYFILE, "<", "MyFile.txt"; # The < is for read mode
while ($line = <MYfILE>) {
    foo($line); #do whatever, one line at a time
}

If you want to read all lines at once into an array, you can just

my @lines = <MYFILE>;

Or to read it all in one string, change the newline separator $/ to be undefined

{
local $/; #initialized to undef
$file = <MYFILE>;
}

EDIT: I think I finally understand the question:

The OP has a file which, for lack of better terminology, contains questions and responses. Questions always come before responses. Both types of statements are enclosed in double quotes. There is a blank line (ie "\\n\\n" ) between a question and its associated response. The OP wants to read the questions and their associated responses one-by-one (not line-by-line).

There are several approaches to this (without necessarily slurping). One is to assume that double-quotes do not appear anywhere other than at the beginning or end of the strings of interest. I am not sure how valid an assumption this is which makes the following script fragile. Note that the last block is invalid because the answer is not enclosed in double quotes.

#!/usr/bin/perl

use strict;
use warnings;

while (
    defined(my $q = read_statement(\*DATA))
        and defined(my $a = read_statement(\*DATA))
) {
    print "QUESTION: $q\nANSWER: $a\n\n";
}

sub read_statement {
    my ($fh) = @_;

    my $line;
    while ( $line = <$fh> ) {
        last if $line =~ /^"/;
    }
    return unless defined $line;
    return $line if $line =~ /"$/;

    my $statement = $line;
    while ($line = <$fh> ) {
        $statement .= $line;
        last if $line =~ /"$/;
    }
    return unless $statement =~ /"$/;
    return $statement;
}

Test input:

__DATA__
"Hi how are you?"
"Hello

im
fine, thank you!"

"How is the weather?"

"It rained
all week.


It's been
gray

    and cold since the 15th"

"Who are you?"

Sinan

Output:

C:\Temp> t
QUESTION: "Hi how are you?"

ANSWER: "Hello

im
fine, thank you!"


QUESTION: "How is the weather?"

ANSWER: "It rained
all week.


It's been
gray

    and cold since the 15th"

Based on your last comment, I wonder if this is what you want:

#!/usr/bin/env perl
use strict;
use warnings;
use Text::Balanced qw/extract_delimited/;

my $filecontents = do { local $/; <> };

while (my $item = extract_delimited($filecontents, '"')) {
    print "Item: $item\n";
}

It captures as one item each selection in double quotes, however long. (To anticipate: George this is A solution, but, no, I didn't choose to use File::Slurp .)

The operation you are looking for is called 'file slurping' instead of undef-ing $/

use

File::Slurp - Efficient Reading/Writing of Complete Files

here's the summary from the site

  use File::Slurp;

  my $text = read_file( 'filename' ) ;
  my @lines = read_file( 'filename' ) ;

  write_file( 'filename', @lines ) ;

  use File::Slurp qw( slurp ) ;

  my $text = slurp( 'filename' ) ;

It sounds like you want to read all "double-quoted" values inside a file, including those that are split across lines. If that's the case, you can do the following:

my $content = join "", <>;
my @statements = ();
push @statements, $1 while $content =~ /"(.*?)"/msg;

This doesn't handle escaped double-quotes within your quoted values, but your example didn't have any examples of that. If you need to be able to escape quotes, you need to change the regular expression a bit or use Text::Balanced as described above.

With the OP's clarification that he's trying to get quoted strings out of the file, and assuming that each string's closing quote will be at the end of a line, my approach would be:

#!/usr/bin/perl

use strict;
use warnings;

local $/ = qq("\n);    # Extra " to fix SO syntax highlighting

while (my $quot_text = <DATA>) {
  print "Next text:\n$quot_text\n"
}

__DATA__
"Hi how are you?"
"Hello 

im
fine, thank you!"

Which returns:

Next text:
"Hi how are you?"

Next text:
"Hello

im
fine, thank you!"

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM