2010-06-29 11 views

risposta

72
while (<>) { 
print; 
} 

leggerà sia da un file specificato su t egli riga di comando o da stdin se nessun file è dato

Se si sono tenuti questa costruzione loop nella linea di comando, allora si può utilizzare -n opzione:

$ perl -ne 'print;' 

Qui basta mettere codice tra {} dal primo esempio in '' in seconda

+21

+1 + nitpick: "leggerà da uno o più file specificati consecutivamente sulla riga di comando" – msw

+4

... e tutto ciò che dovete fare è scrivere '@ARGV =" /path/to/some/file.ext ";' e legge il file - così puoi persino programmare un file predefinito a determinate condizioni. – Axeman

+2

E se lo script è molto breve, è possibile utilizzare le opzioni -n o -p in perl e specificare l'elaborazione sulla riga di comando: 'perl -n -e '$ _ = uc ($ _); stampare;' yourfile'. Con -p invece di -n, perl stampa automaticamente $ _ alla fine. – mivk

12

è necessario utilizzare <> operatore:

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

Quale può essere compresso per:

print while (<>); 

file arbitrario:

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

L'operatore plain '<>' troverà e leggerà automaticamente da qualsiasi file dato sulla riga di comando. Non c'è bisogno di "se". –

+0

Inoltre non si descrive cosa sta facendo 'shift' qui –

6

fare

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

se volete leggere una sola riga

+0

legge solo da STDIN, non dal file specificato. L'operatore diamante è * esattamente * ciò che l'OP sta cercando. –

34

Ciò fornisce una variabile chiamata a lavorare con:

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

Per leggere un file, pipe in questo modo:

program.pl < inputfile 
+7

+1 per evitare il comune codice illeggibile Perl – MikeKulls

+3

-1, poiché foreach esegue lo slurp dell'intero file. Meglio assegnare alla linea in un ciclo while. Inoltre, Perl ha un comportamento magico incorporato per le parentesi angolari nude, quindi dovresti aver detto while (my $ line = <>). Quindi non è necessario alcun reindirizzamento. –

+2

La prima riga dovrebbe contenere 'foreach my $ line () {' Sono d'accordo con @MikeKulls. Non è colpa di Perl se gli script Perl sono illeggibili. I programmatori sono la colpa qui! – tiktak

10

Il il modo "più scivoloso" in determinate situazioni è sfruttare il -n switch. Incapsula implicitamente il codice con un ciclo while(<>) e gestisce l'input in modo flessibile.

In slickestWay.pl:

 
#!/usr/bin/perl -n 

BEGIN: { 
    # do something once here 
} 

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

Nella riga di comando:

chmod +x slickestWay.pl 

Ora, a seconda del vostro ingresso effettuare una delle seguenti operazioni:

  1. Attendere che l'input dell'utente

    ./slickestWay.pl 
    
  2. leggere dal file (s) di nome in argomenti (senza reindirizzamento richiesto)

    ./slickestWay.pl input.txt 
    ./slickestWay.pl input.txt moreInput.txt 
    
  3. utilizzare un tubo

    someOtherScript | ./slickestWay.pl 
    

Il blocco BEGIN è necessario se è necessario inizializzare una sorta di interfaccia orientata agli oggetti, come Text :: CSV o alcuni di essi, che è possibile aggiungere allo shebang con -M.

-l e -p sono anche i tuoi amici.

5

Se c'è un motivo per cui non è possibile utilizzare utilizzando la semplice soluzione fornita da ennuikiller in alto, sarà necessario utilizzare Typeglobs per manipolare i file handle. Questo è molto più lavoro. Questo esempio copia dal file in $ARGV[0] a quello in $ARGV[1]. Il valore predefinito è STDIN e STDOUT rispettivamente se i file non sono specificati.

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 per un modo che funzionerà se il nome del file da * non è * fornito sulla riga di comando ma da qualche altra parte (in alcune variabili, letta dal file di configurazione ecc. - si sostituisce '$ ARGV [0]' etc con altra variabile) dove tutte le altre risposte falliscono ... –

+0

Oppure, per leggere, basta "non spostare" il nome del file su '@ ARGV' e usare l'operatore diamond,' <> '. –

0

Ecco come ho fatto uno script che potrebbe prendere entrambi gli ingressi di linea di comando o di avere un file di testo reindirizzato.

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


Ciò riassegnare il contenuto del file in @ARGV, da lì basta @ARGV processo come se qualcuno stesse incluse le opzioni della riga di comando.

ATTENZIONE

Se nessun file viene reindirizzato, il programma siederà la loro inattività, perché è in attesa di input da STDIN.

Non ho trovato un modo per rilevare se un file viene reindirizzato per eliminare il problema STDIN.

+0

Questo è un approccio interessante, ma non quello che l'OP chiedeva. Ciò rende possibile passare un singolo nome di file come argomento, i cui contenuti sono usati come argomenti della riga di comando. OP cercava qualcosa di diverso. Inoltre, perché il criptico '$ # ARGV <1' invece di (cosa penso di come) più chiaro' @ARGV == 1'? –