¿Cómo puedo procesar una cadena de varias líneas una línea a la vez en perl con el uso estricto en su lugar?

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

Pregunta

Estoy tratando de descubrir la forma correcta aprobada por PBP de procesar una cadena de varias líneas, línea por línea. Muchos codificadores de Perl sugieren tratar la cadena de varias líneas como un identificador de archivo, que funciona bien a menos que tenga & "; Use estricto &"; en tu guion Luego recibe una advertencia del compilador sobre no poder usar una cadena como símbolo mientras se usan referencias estrictas.

Aquí hay un ejemplo de trabajo simple 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";

Observe que " use estricto " La línea está comentada. Cuando ejecuto este script sin uso estricto, obtengo lo que quiero y espero:

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

Aquí está el problema, sin embargo. Cuando descomente el & Quot; use estricto & Quot; línea, recibo la siguiente advertencia o error de 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 línea 8 es " open $ ResultsHandle, '<', \ $ return; " línea, por cierto. Entonces, dado que Perl Best Practices requiere que use estricto, ¿cómo espera PBP que procese una cadena de varias líneas de una en una? ¿Alguna sugerencia de la comunidad SO?

¡Gracias!

¿Fue útil?

Solución

No inicialice $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";

Si deja open() sin definir antes de use strict, se completará con una referencia al identificador de archivo. Debido a que lo estaba configurando en una cadena, <=> supuso que se suponía que era una referencia simbólica a una variable en su lugar --- no se permitía en <=>.

Otros consejos

La manera más sucinta de PBP es usar abierto de esta manera:

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

Esto elimina la necesidad de que " my $ Resultshandle; " declaración y evita incurrir en esa advertencia estricta con la que se encontró.

También puede usar una expresión regular como iterador:

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

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

Esto es un poco menos complicado en comparación con el uso de un identificador de archivo que representa una cadena.

Convierta la cadena de varias líneas en una lista de cadenas de una sola línea 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
    }
}

Cambiar

my $ResultsHandle = "";

a

my $ResultsHandle;

Abra un identificador de archivo utilizando una tubería de " dir " comando.

Por ejemplo.

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

Se puede lograr un mejor resultado con la división:

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
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top