2010-06-29 26 views

Respuesta

72
while (<>) { 
print; 
} 

aparece ya sea a partir de una archivo especificado en t que la línea de comandos o de la entrada estándar si no hay ningún archivo se da

Si se le requiere esta construcción de bucle en la línea de comandos, entonces puede usar -n opción:

$ perl -ne 'print;' 

Aquí sólo hay que poner el código entre {} del primer ejemplo '' en el segundo

+21

+1 + nitpick: "leerá de uno o más archivos consecutivamente especificados en la línea de comandos" – msw

+4

... y todo lo que tiene que hacer es escribir '@ARGV =" /path/to/some/file.ext ";' y lee el archivo, por lo que incluso puede programar un archivo predeterminado en determinadas condiciones. – Axeman

+2

Y si su script es muy corto, puede usar las opciones -n o -p para perl, y especificar su procesamiento en la línea de comando: 'perl -n -e '$ _ = uc ($ _); impresión;' yourfile'. Con -p en lugar de -n, perl imprime automáticamente $ _ al final. – mivk

12

Es necesario utilizar <> operador:

while (<>) { 
    print $_; # or simply "print;" 
} 

que puede ser compactado a:

print while (<>); 

arbitraria de archivos:

open F, "<file.txt" or die $!; 
while (<F>) { 
    print $_; 
} 
close F; 
-2
if(my $file = shift) { # if file is specified, read from that 
    open(my $fh, '<', $file) or die($!); 
    while(my $line = <$fh>) { 
    print $line; 
    } 
} 
else { # otherwise, read from STDIN 
    print while(<>); 
} 
+7

El operador '' '' simple buscará y leerá automáticamente de cualquier archivo (s) dado (s) en la línea de comando. No es necesario el 'si'. –

+0

Tampoco se describe lo que 'shift' está haciendo aquí –

6

hacer

$userinput = <STDIN>; #read stdin and put it in $userinput 
chomp ($userinput); #cut the return/line feed character 

si desea leer una sola línea

+0

Solo lee desde STDIN, no desde el archivo especificado. El operador de diamantes es * exactamente * lo que el OP está buscando. –

34

Esto proporciona una variable llamada para trabajar con:

foreach $line (<STDIN>) { 
    chomp($line); 
    print "$line\n"; 
} 

Para leer un archivo, una conexión en este aspecto:

program.pl < inputfile 
+7

+1 para evitar el código abreviado de Perl, muy común, ilegible – MikeKulls

+3

-1, ya que foreach sorberá todo el archivo. Es mejor asignar a la línea en un ciclo while. Además, Perl tiene un comportamiento mágico incorporado para los corchetes angulados desnudos, por lo que debería haber dicho while (my $ line = <>). Entonces no es necesaria una redirección. –

+2

La primera línea debe leer 'foreach my $ line () {' Estoy de acuerdo con @MikeKulls. No es culpa de Perl si las secuencias de Perl son ilegibles. ¡Los programadores tienen la culpa aquí! – tiktak

10

El La forma "más hábil" en ciertas situaciones es aprovechar el -n switch. Envuelve implícitamente su código con un bucle while(<>) y maneja la entrada de forma flexible.

En slickestWay.pl:

 
#!/usr/bin/perl -n 

BEGIN: { 
    # do something once here 
} 

# implement logic for a single line of input 
print $result; 

En la línea de comandos:

chmod +x slickestWay.pl 

Ahora, dependiendo de su entrada siga uno de los siguientes:

  1. esperar a la entrada del usuario

    ./slickestWay.pl 
    
  2. Leer de archivo (s) nombrado en argumentos (sin cambio de dirección requiere)

    ./slickestWay.pl input.txt 
    ./slickestWay.pl input.txt moreInput.txt 
    
  3. uso de una tubería

    someOtherScript | ./slickestWay.pl 
    

El bloque BEGIN es necesario si usted necesita para inicializar algún tipo de interfaz orientada a objetos, como Text :: CSV o algo así, que puede agregar al shebang con -M.

-l y -p también son sus amigos.

5

Si hay una razón por la que no se puede utilice la solución simple provista por ennuikiller arriba, entonces tendrá que usar Typeglobs para manipular manejadores de archivos. Esto es mucho más trabajo. Este ejemplo copia desde el archivo en $ARGV[0] al de $ARGV[1]. Se establece de manera predeterminada en STDIN y STDOUT, respectivamente, si los archivos no están especificados.

use English; 

my $in; 
my $out; 

if ($#ARGV >= 0){ 
    unless (open($in, "<", $ARGV[0])){ 
     die "could not open $ARGV[0] for reading."; 
    } 
} 
else { 
    $in = *STDIN; 
} 

if ($#ARGV >= 1){ 
    unless (open($out, ">", $ARGV[1])){ 
     die "could not open $ARGV[1] for writing."; 
    } 
} 
else { 
    $out = *STDOUT; 
} 

while ($_ = <$in>){ 
    $out->print($_); 
} 
+0

+1 por una forma que funcionará si el nombre de archivo para leer desde * no está * en la línea de comandos sino en otro lugar (en alguna variable, lea desde el archivo de configuración, etc.) simplemente reemplace '$ ARGV [0]' etc. con otra variable) donde todas las demás respuestas fallan ... –

+0

O, para leer, simplemente "desplace" el nombre de archivo a '@ ARGV' y use el operador de diamante,' <> '. –

0

Aquí es cómo hice un script que podría tomar como entradas de línea de comandos o un archivo de texto redirigido.

if ($#ARGV < 1) { 
    @ARGV =(); 
    @ARGV = <>; 
    chomp(@ARGV); 
} 


Este reasignará el contenido del archivo a @ARGV, a partir de ahí sólo @ARGV proceso como si alguien estaba incluyendo opciones de línea de comandos.

ADVERTENCIA

Si se redirige ningún archivo, el programa se sentará a su inactividad, ya que está a la espera para la entrada de STDIN.

No he encontrado una forma de detectar si un archivo está siendo redirigido aún para eliminar el problema STDIN.

+0

Este es un enfoque genial, pero no lo que el OP estaba pidiendo. Esto permite pasar un único nombre de archivo como argumento, cuyo contenido se usa como argumentos de línea de comandos. OP estaba buscando algo diferente. Además, ¿por qué el críptico '$ # ARGV <1' en lugar de (lo que pienso como) es más claro' @ARGV == 1'? –

Cuestiones relacionadas