2010-07-23 14 views
16

Tengo un archivo, someFile, así:¿Cómo puedo pasar los argumentos a Perl one-liner?

$cat someFile 
hdisk1 active 
hdisk2 active 

Puedo usar este script para comprobar:

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

Estoy tratando de convertirlo en 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 

Exportación la variable d en el script de shell y obtengo el valor usando %ENV en Perl. ¿Hay alguna forma mejor de pasar este valor al Perl one-liner?

+4

Por qué no realizar el bucle directamente en Perl? Entonces su script de shell simplemente desaparece. – FMc

+0

en lugar de usar 'cat file | perl ... 'es más fácil de usar' perl ... file'. – TrueY

Respuesta

24

Puede activar argumento de línea de comandos rudimentaria con el interruptor de "s". Se define una variable para cada argumento que comienza con un guion. El -- indica dónde comienzan sus argumentos de línea de comando.

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

Ver: perlrun

+0

Muchas gracias. Nunca realmente lo descubrí. Siempre escribió una secuencia de comandos cuando necesita argumentos de línea de comando. – saudic

1

paso en la línea de comandos, y que estará disponible en @ARGV:

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

Tenga en cuenta que el operador shift en este contexto elimina el primer elemento de @ARGV, que es $d en este caso.

+0

Vale la pena señalar que @gbacon ha convertido 'cat a | perl -n' a 'perl -n a'. Si le da un nombre de archivo como parámetro a perl, está disponible para el ciclo -n. – justintime

0

que se ve bien, pero me gustaría usar:

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

Si usted está teniendo problemas para escribir una sola línea, tal vez es un poco difícil para una sola línea (sólo mi opinión). Estoy de acuerdo con la sugerencia de @ FM y hago todo en Perl. Leer el resto del documento y luego probarlo:

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

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

que podría hacer que un bucle, pero eso sería más largo. Por supuesto, depende en cierto modo del tamaño del archivo.

Tenga en cuenta que todos los ejemplos de Perl hasta ahora imprimirán un mensaje para cada coincidencia, ¿puede estar seguro de que no hay duplicados?

0

combinar algunas de las sugerencias anteriores y añadiendo mi propia azúcar a la misma, lo haría de esta manera:

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

[valor] puede ser un número (es decir, 2), un rango (es decir, 2 -4), una lista de números diferentes (es decir, 2 | 3 | 4) (o cualquier otra cosa, que es un patrón válido) o incluso una variable de bash que contiene uno de los, ejemplo:

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

y [archivo ] es su nombre de archivo (es decir, someFile).

0

Mi solución es un poco diferente. Llegué a su pregunta con una búsqueda en Google, el título de su pregunta, pero estoy tratando de ejecutar algo diferente. Aquí está en caso de que ayude a alguien:

FYI, estaba usando tcsh en Solaris.

que tenía la siguiente de una sola línea:

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

que da salida el valor:

2013-05-06 

yo estaba tratando de colocar esto en un script de shell para que pudiera crear un archivo con una fecha en el nombre de archivo, de X números de días en el pasado. Intenté:

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

Pero esto no funcionó debido a la sustitución de la variable. Tuve que perder el tiempo con las citas, para lograr que lo interpretara correctamente. Traté de encerrar todo el lote entre comillas dobles, pero esto hizo que el comando Perl no fuera sintácticamente correcto, ya que interfería con las comillas dobles en torno al formato de fecha. Terminé con:

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

que funcionó muy bien para mí, sin tener que recurrir a cualquier variable de exportación de fantasía.

Me doy cuenta de que esto no responde exactamente a su pregunta específica, pero contestó el título y podría ayudar a otra persona.

3

veces rompiendo el recinto Perl es un buen truco para estos de una sola línea:

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