2009-09-25 6 views
-1

Je veux juste lire plusieurs lignes dans un fichier. Par exemple, dans sample.txtComment lire plusieurs lignes en Perl?

 
"Hi, how are you?" 
"Hello 

I'm 
fine, thank you!" 

Maintenant, mon problème est de savoir comment puis-je lire la deuxième déclaration sans enlever la nouvelle ligne dans la phrase?

EDIT:

Il semble que mes questions ne sont pas claires. Je pense que je devrais modifier ceci: Dans mes exemples ci-dessus, je dois obtenir l'ensemble,

 
"Hello 

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

La question n'est pas claire. Pourquoi auriez-vous besoin de supprimer une nouvelle ligne pour lire la deuxième déclaration? – innaM

+1

La langue est "Perl", pas "PERL". – Ether

+0

Non, ce que je veux dire est, comment puis-je lire la deuxième déclaration déclaration complète, y compris le retour à la ligne. Merci. – domlao

Répondre

2

EDIT: Je pense que je comprends enfin la question:

L'OP a un fichier qui, faute d'une meilleure terminologie, contient des questions et des réponses. Les questions viennent toujours avant les réponses. Les deux types d'instructions sont placés entre guillemets. Il y a une ligne vide (c'est-à-dire "\n\n") entre une question et sa réponse associée. Le PO veut lire les questions et leurs réponses associées une à une (pas ligne par ligne).

Il y a plusieurs approches à cela (sans nécessairement slurping). L'une consiste à supposer que les guillemets n'apparaissent nulle part ailleurs qu'au début ou à la fin des chaînes d'intérêt. Je ne suis pas sûr de la validité de cette supposition qui rend le script suivant fragile. Notez que le dernier bloc n'est pas valide car la réponse n'est pas entre guillemets.

#!/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; 
} 

Entrée test:

__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 

Sortie:

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" 
+0

c'est genre de hacky et d'erreur sujettes. pourrait aussi bien l'annuler –

+3

Qu'est-ce qui rend ce hacky et l'erreur sujettes? L'entrée semble être des enregistrements. Les enregistrements semblent être séparés par une ligne vide (donc deux nouvelles lignes). La manière standard de lire des enregistrements est de redéfinir $/- * c'est * le Séparateur d'Enregistrement d'Entrée après tout. –

+0

Bien sûr, je ne suis pas sûr que Sinan a réellement répondu à la question posée, mais c'est une autre affaire entièrement :) –

6

Si vous voulez lire toutes lignes à la fois, changer la ligne séparateur $/:

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

Si vous voulez lire deux lignes à la fois, vous pouvez simplement lire deux lignes à la fois.

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

Je vois, donc la deuxième phrase restera la même, je veux dire avec les caractères de nouvelle ligne? Merci – domlao

+0

c'est une façon de le faire, mais c'est un peu indirect.File :: Slurp est préférable –

+0

Vouliez-vous redéfinir '$ /' plutôt que '$,' afin de slurper le fichier? (Est-ce que '$,' n'est pas le séparateur d'enregistrement de sortie?) – Telemachus

3

Je ne suis pas sûr de ce que vous entendez par « sans enlever le saut de ligne » dans la phrase, mais à lire un fichier, ligne par ligne, vous feriez quelque chose comme

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

Si vous voulez lire toutes les lignes à la fois dans un tableau, vous pouvez juste

my @lines = <MYFILE>; 

Ou de le lire en une seule chaîne, changer le séparateur de $ newline/non défini à 0

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

c'est une façon de le faire, mais c'est légèrement indirect. –

1

L'opération que vous recherchez est appelé «fichier siphonage au lieu de FNUD-ing/$

utiliser

File::Slurp - efficace lecture/écriture des dossiers complets

est ici le résumé du 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') ; 
+0

File :: Slurp est une bonne suggestion. Ne vous donnant pas de +1 parce que vous avez ressenti le besoin de vous plaindre des réponses de tous les autres. – SquareCog

+1

Idem. Si vous avez une réponse différente, postez simplement votre réponse. Ne commentez pas toutes les autres réponses en disant qu'elles sont nulles. C'est pour cela que le système de vote est - si votre réponse est vraiment la meilleure, elle trouvera son chemin vers le haut de la liste. –

+0

il se plaint, mais il a donné la meilleure réponse :) –

3

Sur la base de votre dernier commentaire, je me demande si c'est ce que vous voulez:

#!/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"; 
} 

Il capture comme un élément chaque sélection entre guillemets doubles, quelle qu'en soit la longueur. (Pour anticiper: George c'est une solution, mais, non, je n'ai pas choisi d'utiliser File::Slurp.)

1

Il semble que vous vouliez lire toutes les valeurs "entre guillemets" dans un fichier, y compris ceux qui sont divisé sur les lignes. Si tel est le cas, vous pouvez effectuer les opérations suivantes:

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

Cela ne gère pas les guillemets doubles échappées dans vos valeurs indiquées, mais votre exemple n'a pas eu d'exemples. Si vous devez être en mesure d'échapper des guillemets, vous devez modifier un peu l'expression régulière ou utiliser Text :: Balanced comme décrit ci-dessus.

1

Avec la précision apportée OP qu'il essaie d'obtenir des chaînes entre guillemets sur le fichier, et en supposant que la citation de clôture de chaque chaîne sera à la fin d'une ligne, mon approche serait:

#!/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!" 

qui retourne :

Next text: 
"Hi how are you?" 

Next text: 
"Hello 

im 
fine, thank you!" 
Questions connexes