2012-04-01 15 views
5

Quiero conocer las mejores prácticas aquí. Supongamos que quiero obtener el contenido de alguna línea de un archivo. Puedo usar un comando de shell de una línea para obtener mi respuesta, o escribir una subrutina, como se muestra en el siguiente código.En scripts Perl, ¿debemos usar comandos de shell o llamar a funciones de Perl que imiten las operaciones de shell?

Un archivo de texto denominado some_text:

She laughed. Then both continued eating in silence, like strangers, 
but after dinner they walked side by side; and there sprang up 
between them the light jesting conversation of people who are free 
and satisfied, to whom it does not matter where they go or what 
they talk about. 

código para obtener el contenido de la línea 5 del archivo

#!perl 
use warnings; 
use strict; 

my $file = "some_text"; 
my $lnum = 5; 
my $shellcmd = "awk 'NR==$lnum' $file"; 
print qx($shellcmd); 
print getSrcLine($file, $lnum); 

sub getSrcLine { 
    my($file, $lnum) = @_; 
    open FILE, $file or die "$!"; 
    my @ray = <FILE>; 
    return $ray[$lnum-1]; 
} 

lo pregunto porque veo un montón de scripts de Perl, donde en algún momento, se invocó un comando de shell, mientras que en algún momento posterior, la misma tarea se realizó mediante una llamada a una función (de biblioteca o manuscrita), por ejemplo, rm -rf frente a File::Path::rmtree. Solo quiero que sea consistente.

¿Qué es lo que se recomienda hacer?

+0

La manera recomendada depende de la intención del código. Si desea ejecutar en la máquina Non-Unix, vaya a las bibliotecas de Perl, mire el enlace que he publicado. Espero que esto ayude ... – Rajeev

+0

Quizás cada uno de los scripts fue desarrollado durante un período de tiempo, posiblemente por múltiples programadores. Los guiones evolucionaron, y el código no es 100% auto consistente, dependiendo en parte de cómo los involucrados tenían más o menos experiencia con Perl y shell. –

+2

Tenga en cuenta que aunque sorber un archivo de 5 líneas completo para obtener la quinta línea no es demasiado doloroso, probablemente sea una estrategia subóptima para obtener la quinta línea de un archivo de un millón de líneas. –

Respuesta

13

Si hay una función Perl para la operación, Perl cree que debería usar su versión. Sin embargo, debe dar un ejemplo de un módulo Perl que proporciona una forma pura de Perl para hacerlo. Eso es muy diferente. No hay una respuesta única (como en la mayoría de las cosas), por lo que tiene que decidir por sí mismo qué hacer:

  • ¿El enfoque de Perl pura hacerlo correctamente? Por ejemplo, File::Copy tiene algunas limitaciones porque toma algunas decisiones incómodas para el usuario, por lo que muchas personas piensan que no funciona. Ver, por ejemplo, File::Copy versus cp/mv.

  • ¿El enfoque puro de Perl lo hace en un tiempo aceptable? A veces, el programa externo es mucho más rápido. A veces es mucho más lento.

  • Los comandos externos generalmente son portátiles dentro de una familia de sistemas (por ejemplo, todos los sistemas similares a Linux) pero probablemente no entre familias (por ejemplo, Windows y Linux). Su tolerancia para eso podría afectar su respuesta. Incluso si cree que está ejecutando el mismo comando, los diferentes sabores de los sistemas tipo Unix podrían tener diferentes interruptores para las operaciones.

  • Pasar argumentos complicados (espacios, comillas y caracteres especiales) a comandos externos puede hacer que llore. Tienes que hacer un montón de trabajo complicado para asegurarte de que manejas los argumentos correctamente. Sin embargo, a las subrutinas de Perl no les importa.

  • Tiene que prestar mucha más atención a lo que está haciendo cuando usa el comando externo. Si solo llama al rm, Perl buscará en su PATH y usará lo primero llamado rm. Eso no significa que es el programa que crees que es. Escribo bastante sobre esto en las "Técnicas de programación segura" en Mastering Perl.

  • Si el enfoque puro de Perl requiere un módulo, especialmente si ese módulo tiene muchas dependencias complicadas, es posible que en el futuro esté listo para la dependencia o la distribución.

Personalmente, comienzo con el enfoque puro de Perl hasta que no funciona para la situación.

Para sus ejemplos particulares, usaría Perl. Destruir a awk, que es un proto-Perl, es simplemente extraño. Deberías poder hacer todo lo que no hace, Perl. Si usted tiene un programa awk, puede convertirlo en Perl con el programa a2p:

NR==5 

a2p resulta que en (módulo algunos bits de configuración en el inicio):

while (<>) { 
    print $_ if $. == 5; 
} 

en cuenta que una aún escanea todo el archivo aunque tengas la quinta línea. Sin embargo, se puede utilizar el programa traducido como punto de partida:

while (<>) { 
    if($. == 5) { 
     print; 
     last; 
     } 
} 

no creo que usted debe pagar a algún otro programa para evitar que el código Perl.

Para eliminar un árbol de directorios, me gusta File::Path. Tiene algunas dependencias, pero todas están en la biblioteca estándar de Perl. Hay muy poco dolor, si alguno, asociado con ese módulo. Lo usaría hasta que me encontrara con un problema donde no funcionaba.

+0

gracias por una respuesta detallada. Me gustó el punto sobre la seguridad en particular, ya que no lo considero mucho mientras estoy programando en Perl. Además, conocí el programa a2p, ¡que es realmente útil! Ahora estoy convencido de que debo tratar de evitar los comandos de shell externos en mis scripts, siempre que Perl pueda hacer lo mismo de manera confiable. – Unos

+0

Excelente respuesta. La única adición que haría es con respecto a los requisitos del guión. Si está escribiendo un programa de uso único, desembolsar un comando * nix es bastante razonable si le ahorra tiempo. Hice esto recientemente en una secuencia de comandos de archivo de datos para un script de exportación a importación de Datbase. Era más rápido enviar un comando externo por una parte, y el script se descartaba una vez que se ejecutaba (correctamente). Si estuviera escribiendo un programa que hiciera una función similar cada semana, me habría tomado el tiempo de implementarlo correctamente en Perl, si pudiera. –

4

Si desea que su aplicación sea portátil para sistemas que no sean Unix, entonces definitivamente codifique todo en Perl.

De lo contrario, depende de usted ... crear un nuevo proceso es más lento, pero si no es importante para la tarea, entonces no importa. Personalmente, elegiría la solución que puedo implementar más rápidamente.

2

Me parece que el código que funciona debe ser la primera prioridad. El tuyo falla si el nombre del archivo tiene un espacio, por ejemplo.

El uso del shell hace que sea más difícil codificar correctamente, ya que su programa necesita generar correctamente otro programa para ser ejecutado por sh. (Este problema desaparece si utiliza la versión multi-arg del sistema para evitar el shell).

Además, el uso de herramientas externas puede dificultar el manejo de errores. ¡Ni siquiera intentaste hacerlo!

Por otro lado, hay varias razones para usar herramientas externas. Por ejemplo, Perl no proporciona una utilidad de copia de archivo tan buena como cp; usar la herramienta sort le permite ordenar archivos grandes arbitrarios con RAM limitada; etc.

Cuestiones relacionadas