2010-07-23 14 views
16

Ho un file, someFile, in questo modo:Come faccio a passare meglio gli argomenti a un liner Perl?

$cat someFile 
hdisk1 active 
hdisk2 active 

Io uso questo script di shell per controllare:

$cat a.sh 
#!/usr/bin/ksh 
for d in 1 2 
do 
    grep -q "hdisk$d" someFile && echo "$d : ok" 
done 

Sto cercando di convertirlo in Perl:

$cat b.sh 
#!/usr/bin/ksh 
export d 
for d in 1 2 
do 
    cat someFile | perl -lane 'BEGIN{$d=$ENV{'d'};} print "$d: OK" if /hdisk$d\s+/' 
done 

Esportare la variabile d nello script della shell e ottenere il valore utilizzando %ENV in Perl. Esiste un modo migliore per trasferire questo valore alla copertina di Perl?

+4

Perché non eseguire il loop direttamente in Perl? Quindi lo script della shell scompare semplicemente. – FMc

+0

Invece di usare 'cat file | perl ... 'è più semplice usare' perl ... file'. – TrueY

risposta

24

È possibile attivare rudimentale argomento della riga di comando con l'interruttore "s". Una variabile viene definita per ogni argomento che inizia con un trattino. Il -- indica dove iniziano gli argomenti della riga di comando.

for d in 1 2 ; do 
    cat someFile | perl -slane ' print "$someParameter: OK" if /hdisk$someParameter\s+/' -- -someParameter=$d; 
done 

See: perlrun

+0

Grazie mille. Non l'ho mai capito veramente. Ha sempre scritto uno script quando necessitava di argomenti da riga di comando. – saudic

1

passarlo sulla riga di comando, e sarà disponibile in @ARGV:

for d in 1 2 
do 
    perl -lne 'BEGIN {$d=shift} print "$d: OK" if /hdisk$d\s+/' $d someFile 
done 

Nota che l'operatore shift in questo contesto rimuove il primo elemento di @ARGV, che è $d in questo caso.

+0

Vale la pena sottolineare che @gbacon ha convertito 'cat a | perl -n' a 'perl -n a'. Se si assegna un nome file come parametro a perl, è disponibile per il ciclo -n. – justintime

0

che sembra buona, ma userei:

for d in $(seq 1 2); do perl -nle 'print "hdisk$ENV{d} OK" if $_ =~ /hdisk$ENV{d}/' someFile; done 
2

Se si hanno difficoltà a scrivere una battuta, forse è un po 'difficile per una linea (solo la mia opinione). Sarei d'accordo con il suggerimento di @ FM e farei il tutto in Perl. Leggi l'intero file e testalo:

use strict; 
    local $/ = '' ; # Read in the whole file 
    my $file = <> ; 

    for my $d (1 .. 2) 
    { 
     print "$d: OK\n" if $file =~ /hdisk$d\s+/ 
    } 

Si potrebbe fare il ciclo, ma sarebbe più lungo. Ovviamente dipende in qualche modo dalla dimensione del file.

Si noti che tutti gli esempi Perl finora stamperanno un messaggio per ogni partita: si può essere sicuri che non vi siano duplicati?

0

Combinando alcuni dei suggerimenti precedenti e aggiungendo il mio zucchero ad esso, lo farei in questo modo:

perl -se '/hdisk([$d])/ && print "$1: ok\n" for <>' -- -d='[value]' [file] 

[valore] può essere un numero (ad esempio 2), un intervallo (ad esempio 2 -4), un elenco di numeri diversi (per esempio 2 | 3 | 4) (o quasi qualsiasi altra cosa, che è un modello valido) o addirittura una variabile bash contenente uno di quelli, esempio:

d='2-3' 
perl -se '/hdisk([$d])/ && print "$1: ok\n" for <>' -- -d=$d someFile 

e [di file ] è il tuo nome file (ovvero, someFile).

0

La mia soluzione è leggermente diversa. Sono giunto alla tua domanda con una ricerca su Google il titolo della tua domanda, ma sto cercando di eseguire qualcosa di diverso. Qui è nel caso in cui aiuti qualcuno:

FYI, stavo usando tcsh su Solaris.

ho avuto il seguente one-liner:

perl -e 'use POSIX qw(strftime); print strftime("%Y-%m-%d", localtime(time()-3600*24*2));' 

che emette il valore:

2013-05-06 

stavo cercando di mettere questo in uno script di shell in modo da poter creare un file con una data nel nome del file, di X numeri di giorni nel passato. Ho provato:

set dateVariable=`perl -e 'use POSIX qw(strftime); print strftime("%Y-%m-%d", localtime(time()-3600*24*$numberOfDaysPrior));'` 

Ma questo non ha funzionato a causa di sostituzione variabile. Ho dovuto scherzare con il quoting, per farlo interpretare correttamente. Ho provato a racchiudere l'intero lotto tra virgolette doppie, ma questo ha reso il comando Perl non corretto in modo sintattico, poiché ha incasinato le doppie virgolette sul formato data. Ho finito con:

set dateVariable=`perl -e "use POSIX qw(strftime); print strftime('%Y-%m-%d', localtime(time()-3600*24*$numberOfDaysPrior));"` 

Che ha funzionato benissimo per me, senza dover ricorrere a qualsiasi esportazione di variabili di fantasia.

Mi rendo conto che questo non corrisponde esattamente alla tua domanda specifica, ma ha risposto al titolo e potrebbe aiutare qualcun altro!

3

volte rompendo l'involucro Perl è un buon trucco per queste battute:

for d in 1 2 ; do cat kk2 | perl -lne ' print "'"${d}"': OK" if /hdisk'"${d}"'\s+/';done 
Problemi correlati