Come posso elaborare una stringa a più righe una riga alla volta in perl con un uso rigoroso in atto?

StackOverflow https://stackoverflow.com/questions/1445426

Domanda

Sto cercando di capire il modo corretto PBP approvato per elaborare una stringa a più righe una riga alla volta. Molti programmatori Perl suggeriscono di trattare la stringa multilinea come un filehandle, che funziona bene a meno che tu non abbia & Quot; usa il rigoroso & Quot; nella tua sceneggiatura. Quindi viene visualizzato un avviso dal compilatore per non essere in grado di utilizzare una stringa come simbolo mentre sono in uso rigidi riferimenti.

Ecco un semplice esempio funzionante del problema:

#use strict;
use warnings; 

my $return = `dir`;
my $ResultsHandle = "";
my $matchLines = "";
my $resultLine = "";
open $ResultsHandle, '<', \$return;
while (defined ($resultLine = <$ResultsHandle>)) {
    if ($resultLine =~ m/joe/) {
        $matchLines = $matchLines . "\t" . $resultLine;
    }
}
close($ResultsHandle);
print "Original string: \n$return\n";
print "Found these matching lines: \n$matchLines\n";

Nota che il " usa il rigoroso " la riga è commentata. Quando eseguo questo script senza usare rigoroso, ottengo ciò che voglio e mi aspetto:

Original string: 
 Volume in drive D has no label.
 Volume Serial Number is 50D3-54A6

 Directory of D:\Documents and Settings\username\My Documents\Eclipse\myTestProject

09/18/2009  11:38 AM    <DIR>          .
09/18/2009  11:38 AM    <DIR>          ..
09/18/2009  11:36 AM               394 .project
09/18/2009  11:37 AM                 0 joe.txt
09/18/2009  11:37 AM                 0 joey.txt
09/18/2009  11:38 AM                 0 kurt.txt
09/18/2009  11:43 AM               497 main.pl
09/18/2009  11:38 AM                 0 shane.txt
               6 File(s)            891 bytes
               2 Dir(s)   6,656,188,416 bytes free

Found these matching lines: 
    09/18/2009  11:37 AM                 0 joe.txt
    09/18/2009  11:37 AM                 0 joey.txt

Ecco il problema, però. Quando decomprimo il & Quot; uso il rigoroso & Quot; riga, ricevo il seguente avviso o errore da Perl:

Can't use string ("") as a symbol ref while "strict refs" in use at D:/Documents and Settings/username/My Documents/Eclipse/myTestProject/main.pl line 8.

La riga 8 è la quot! &; apri $ ResultsHandle, '<', \ $ return; " linea, a proposito. Quindi, poiché le best practice del Perl mi richiedono di usare rigorose, come si aspetta che PBP elabori una stringa multi linea una riga alla volta? Qualche suggerimento da parte della comunità SO?

Grazie!

È stato utile?

Soluzione

Non inizializzare $ResultsHandle:

use strict;
use warnings; 

my $return = `dir`;
my $ResultsHandle;  # <-- leave undefined
my $matchLines = "";
my $resultLine = "";
open $ResultsHandle, '<', \$return;
while (defined ($resultLine = <$ResultsHandle>)) {
    if ($resultLine =~ m/joe/) {
        $matchLines = $matchLines . "\t" . $resultLine;
    }
}
close($ResultsHandle);
print "Original string: \n$return\n";
print "Found these matching lines: \n$matchLines\n";

Se si lascia open() non definito prima di use strict, verrà compilato con un riferimento all'handle del file. Dato che lo stavi impostando su una stringa, <=> presumeva che avrebbe dovuto essere invece un riferimento simbolico a una variabile --- non consentito in <=>.

Altri suggerimenti

Il modo PBP più conciso è utilizzare open in questo modo:

open my $ResultsHandle, '<', \$return;

Questo elimina la necessità di quella precedente " my $ Resultshandle; " dichiarazione ed evita di incorrere in quel rigoroso avvertimento in cui ti sei imbattuto.

Puoi anche usare un regexp come iteratore:

my $data = q{Hello
This
Is
A
Test};

while( $data =~ /(.+)$/mg) {
    print "line is '$1'\n";
}

Questo è leggermente meno contorto rispetto all'uso di un filehandle che rappresenta una stringa.

Converti la stringa a più righe in un elenco di stringhe a riga singola con split:

my @resultLines = split /\n/, $result;     #   or  /\r\n/ for Windows?
foreach my $resultLine (@resultLines) {
    if ($resultLine =~ m/joe/) {
        $matchLines
            = $matchLines . "\t" 
                 . $resultLine . "\n";  # put \n or \r\n back on the end
    }
}

Cambia

my $ResultsHandle = "";

a

my $ResultsHandle;

Apri un filehandle usando una pipe da " dir " comando.

es.

open my $FOO, "dir|" or die "Can not run 'dir': $!";

Il risultato migliore con la divisione può essere ottenuto tramite:

my $result="LINE1
line2
linE3
";
#attention, /^/m allows properly operate on multiline string using regex
#and ^ is character empty begin all lines
foreach my $resultLine (split /^/m, $result) {
    print $resultline;  #withount '\n' because it have got
    #some checks & operations
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top