¿Cuándo usar Bash y cuándo usar Perl / Python / Ruby? [cerrado]

78

Estamos haciendo todos nuestros scripts con Bash hasta ahora, pero estoy empezando a sentirme un poco tonto al respecto. Si bien, por supuesto, podemos hacer todo lo que queramos con Bash (es bastante poderoso), estoy empezando a preguntarme si no deberíamos usar un lenguaje de secuencias de comandos adecuado (en nuestro caso, probablemente Ruby).

¿Cómo decides cuándo usar Perl / Python / Ruby sobre Bash para un script? No creo que un script de inicio con Ruby tenga sentido, pero ¿qué tal un script un poco más largo que agrega cuentas de correo electrónico?

futlib
fuente
1
Si puedes hacerlo usando cualquiera de los dos, ¿realmente importa? La elección solo es interesante si el script resultante presenta alguna diferencia. Por ejemplo, el tiempo de ejecución puede diferir drásticamente (no es el caso un problema cuando las cuentas de correo electrónico).
Dennis

Respuestas:

44

Dado un problema que ambos pueden resolver, querrá usar el que le resulte más cómodo. En última instancia, hay muchos pequeños detalles, y solo la experiencia puede enseñarle a verlos.

Bash es un lenguaje de script de propósito general como Python, Ruby, Perl, pero cada uno tiene diferentes puntos fuertes sobre el resto. Perl sobresale en el análisis de texto, Python dice ser el más elegante del grupo, los scripts de Bash son excelentes para "entender todo", si sabes a lo que me refiero, y Ruby ... bueno, Ruby es un poco especial en muchos de maneras.

Sin embargo, las diferencias entre ellos solo importan una vez que tenga una buena cantidad de experiencia en secuencias de comandos. Le sugiero que elija un idioma y lo lleve a sus límites antes de pasar al siguiente. Puedes hacer mucho en un script de shell, más de lo que la mayoría de la gente admitiría. Cualquier idioma es tan difícil como quieras. Después de haber escrito un par de cosas en él, cada idioma es "fácil" para usted.

Estar familiarizado con el shell vale la pena rápidamente si vives en Linux, así que tal vez quieras comenzar con eso. Si encuentra una tarea que es imposible o poco práctica de resolver en un script de shell, use otra cosa.

Además, tenga en cuenta que aprender scripting de shell es muy simple. El verdadero poder de esto radica en otros programas, como awk, sed, tr, et al.

mkaito
fuente
Tengo bastante experiencia con las secuencias de comandos bash, como con Ruby, pero a veces todavía no sé qué usar. Elegir basándose en la preferencia personal en ese momento parece una tontería. Pero tienes razón, me preguntaré qué quiero hacer y elegiré la mejor herramienta para el trabajo.
futlib
Personalmente, usaré una escala de los idiomas que conozco bien, en orden ascendente de complejidad y poder, y usaré el más simple que se ajuste a la ley. Pero en realidad, la única forma de saberlo con certeza es escribir su guión en todos los idiomas y comparar el resultado. Todo es más una sensación instintiva que una certeza. Después de algunos años escribiendo guiones, habrá encontrado la mayoría de los "tipos de problemas" y sabrá qué idioma resolvió bien.
mkaito
Solo quería agregar que usando pequeños programas en el paquete GNU coreutils (como tr, sort, uniq) y canalizándolos, es posible realizar muchas tareas.
GMaster
58

TL; DR: use bash solo para instalar un mejor idioma (si aún no está disponible), de lo contrario está desperdiciando un tiempo humano irrecuperable y precioso. Si no puede hacerlo a mano en la línea de comandos sin errores, no escriba con bash / shell.

Es 2015, por lo que consideraría lo siguiente:

  1. sobrecarga de memoria

    • La sobrecarga de memoria en tiempo de ejecución de Ruby / Python en comparación con bash es pequeña (debido a las bibliotecas compartidas), mientras que uno probablemente no puede mantener un script bash no trivial de todos modos (es decir, uno con> 100 líneas), por lo que el uso de memoria no es un factor
  2. tiempo de inicio

    • El inicio de Ruby / Python puede ser un poco más lento, pero es probable que no esté ejecutando muchos procesos completos de Ruby / Python en un ciclo cerrado 100 veces por segundo (si tiene ese tipo de necesidades, bash / shell es demasiada sobrecarga de todos modos y probablemente deba caer a C / C ++)
  3. actuación

    • Casi todo el procesamiento de datos típico será más rápido en Ruby / Python, o al menos comparable (o necesita C / C ++ / Haskel / OCaml / lo que sea)
    • el rendimiento real / cuello de botella en la ejecución (o incluso la productividad) casi nunca será "una falta de uso de bash / shell" (incluso el tablero de conmutación de Ubuntu para el inicio muestra cómo bash es realmente el problema, y ​​un busybox es probablemente el único caso de uso , porque no hay nada más que 'bash' y 'vi' para escribir y ejecutar código, y a menudo no hay forma de agregar / descargar o almacenar cualquier otra cosa)
    • ejecutar otros procesos para hacer el trabajo (como sed / awk / grep) es en realidad una magnitud más lenta que llamar a un método en un objeto vivo en la memoria
  4. productividad

    • es demasiado fácil cometer errores en Bash / shell en comparación con el uso de métodos "reales", parámetros, variables y excepciones en Ruby / Python
    • Agile es mainstream, mientras que Bash no tiene soporte para ello (carece de capacidades de prueba de unidad, bibliotecas, OO, modularidad, linting, introspección, registro, metaprogramación; casi imposible refactorizar sin romper algo)
    • Demasiadas incompatibilidades con otros shells, las variables de entorno menores pueden romper completamente un script (y algunas herramientas de desarrollo importantes como Puppet ignoran las líneas shebang y transmiten o reescriben variables de shell importantes), mientras que Ruby / Python tienen una migración relativamente suave bien definida caminos incluso para cambios importantes de versión
    • aprender un nuevo idioma lleva una fracción del tiempo alternativamente dedicado a depurar scripts de shell debido a problemas específicos del shell (en particular, nombres de variables, sin booleanos, sin excepciones, etc.)
    • incluso los scripts de inicio son una mina terrestre ( especialmente porque pueden fallar durante el inicio del sistema ), y dados los recientes fallos de seguridad con bash, puede que sea mejor usar C simple (con buenas bibliotecas): sí, C necesita compilación, configuración, etc. , pero incluso un simple script de shell puede necesitar un repositorio, luego el control de versiones y el empaquetado de todos modos.
    • lo que esté disponible con sed / awk / grep probablemente ya esté integrado en Ruby / Python, sin que sea una dependencia o "diferencias" entre las versiones de esas herramientas en todas las plataformas (¿y qué si funciona en su configuración?)
  5. seguridad en el empleo
    • ¿Cuál es el punto de asegurar un trabajo que no te gusta? (a menos que le encante pasar todas esas horas con errores de script de shell difíciles de depurar pero triviales)

Creo que no hay razón para usar Bash / Shell si tienes instalado Ruby / Python.

Y probablemente para instalar Ruby / Python ni siquiera necesita un script bash en primer lugar (con la excepción de busybox, algunas herramientas del sistema dependen de que Python / Perl esté presente de todos modos).

Y cada vez que escribe un script de shell, está "practicando" haciendo exactamente eso, en lugar de aprender algo más poderoso / productivo.

¿Por qué la gente usa Bash hoy en día? Porque es un hábito terrible y difícil de romper. Un guión rara vez se "termina para siempre" después de los primeros minutos, sin importar cuán fuertemente las personas tiendan a pensar de esa manera. Junto con la falacia de "es el último error en este script".

Conclusión: use bash / shell solo cuando esté absolutamente obligado a hacerlo (como ~/.bashrcbusybox), porque hoy en día casi nunca es "la herramienta adecuada para el trabajo".

Cezary Baginski
fuente
28

Uso bash cuando mi enfoque principal es el manejo de archivos. Esto podría incluir mover, copiar y renombrar archivos, así como usar archivos como entrada para otros programas o almacenar la salida de otro programa en archivos. Raramente escribo código bash que realmente examine el contenido de un archivo o genere la salida para escribir en un archivo; Lo dejo a los otros programas (que puedo escribir en Perl o Python) que ejecuto a través de bash.

Uso Perl y Python cuando mi enfoque principal es leer datos de archivos, procesar esos datos de alguna manera y escribir resultados en archivos. Si me encuentro usando (en Perl) el systemcomando, los ticks de retroceso o (en python) el subprocessmódulo demasiado, considero escribir el script en bash. Por otro lado, a veces empiezo a agregar tanta funcionalidad a un script bash que eventualmente tiene más sentido reescribirlo en Perl / python en lugar de tratar con el soporte limitado (en comparación) de bash para el alcance variable, funciones, estructuras de datos, etc. .

chepner
fuente
2
También utilicé t0 en Bash cuando se requería la lectura de archivos / generación de texto, pero después de conocer al =~operador que me apoyaba, [[ ]]me encantaba algo de Bash para la lectura simple de archivos
Freedom_Ben
16

Me gustan los criterios establecidos en esta publicación de blog .

  • Si no hay argumentos para pasar, probablemente sea un script de shell.
  • Si no hay mucho para la lógica de control (además de un solo bucle o si / si no), probablemente sea un script de shell.
  • Si la tarea es la automatización de las instrucciones de la línea de comandos, es casi definitivamente un script de shell.
MarkTee
fuente
8

Este análisis de Perl versus Bash me pareció útil ...

http://blogs.perl.org/users/buddy_burden/2012/04/perl-vs-shell-scripts.html

Por conveniencia, estoy copiando un resumen de ese autor 1) cuando bash es mejores hallazgos y 2) cuando perl es mejor conclusión ...

Cuando Bash es mejor ...

  • Fracaso laboral
  • Comandos al salir
  • Procesar líneas de salida de trabajo
  • Aquí documentos
  • Equivalencias de archivo
  • Comparaciones de marca de tiempo de archivo
  • Expansión Tilde

Cuando Perl es mejor ...

Perl sigue superando a bash para la mayoría de las aplicaciones. Las razones por las que podría preferir Perl incluyen (pero no se limitan a):

  • Va a ser más rápido Principalmente porque en realidad no tengo que iniciar nuevos procesos para muchas de las cosas que quiero hacer (basename y dirname son los ejemplos más obvios, pero en general también se pueden eliminar cut, grep, sort y wc).
  • El manejo de cadenas en bash es rudimentario en el mejor de los casos, y todo el asunto de $ IFS es súper torpe.
  • Los condicionales en los scripts de shell pueden ser inestables.
  • Citar en scripts de shell puede ser una pesadilla.
  • La declaración de caso de bash deja mucho que desear más allá de los casos simples (NPI).
  • Las matrices en bash apestan. Los hashes en bash (suponiendo que su bash sea lo suficientemente nuevo como para tenerlos) apestan aún más.
  • Una vez que el procesamiento de archivos o la salida del comando va más allá del caso simple que mencioné anteriormente, Perl comienza a fumar realmente.
  • CPAN.

Por lo tanto, no es como que Bash se haga cargo de Perl en el corto plazo. Pero todavía encuentro, después de todos estos años, que muchas veces un simple script de shell a veces puede ser más simple que un simple script de Perl. Como digo, agradezco todos los intentos de convencerme de lo contrario. Pero, de nuevo, no hay nada de malo en tener algunas herramientas diferentes en su caja de herramientas.

buzz3791
fuente
Curiosamente, en Ruby, todos los puntos (?) No se aplican, porque Ruby tiene at_exit (), realpath (), expand_path (), stat (), heredocs y excepciones ( fail "error" unless system("foobar")).
Cezary Baginski
5

En mi experiencia, bash versus python es una compensación entre el tiempo de desarrollo y la flexibilidad. Una solución rudimentaria a un problema generalmente se puede establecer en un script bash más rápido de lo que se puede hacer en un script python.

Python tenderá a hacerte pensar más en la estructura de tu solución que el script bash equivalente. Python tiene más poder expresivo que un script bash, por lo que tiende a escalar y modificarse mejor con el tiempo. También sigue siendo más legible en general.

Bash está más cerca del sistema de archivos y puede ser excelente para el primer borrador de soluciones a problemas que NO están bien definidos. Por esta razón, un script bash podría ser una buena primera opción para crear un prototipo con la intención de portarlo a Python una vez que se comprenda mejor el problema.

Travis
fuente
4

Bash es un shell de Unix e incluye un lenguaje de script. Es más bien el procesador de comandos. usted controla la forma en que ejecuta los comandos, en realidad los ejecuta.

Perl / Ruby / Python son lenguajes de uso general.

Cuando quieres un script de shell, usas Bash

Si desea una tarea más compleja o no relacionada con el shell. Utiliza Python, etc.

Nunca compararía estos idiomas en realidad. Python, etc.son portátiles. Puedes ejecutarlos en cualquier lugar. Bash es solo para Unix.

Python, etc. tiene toneladas de bibliotecas reutilizables que resuelven millones de tareas.

Es casi lo mismo si preguntas. "Cuándo usar Paint y cuándo usar Photoshop"

Para procesar correos electrónicos, usaría Ruby, una vez más, porque tiene muchas bibliotecas reutilizables.

Pero la mejor manera sería combinar bash y ruby. Eso estaría bien. Al igual que crea una secuencia de comandos de procesamiento de correo electrónico en ruby ​​y bash, invocaría esa secuencia de comandos ruby ​​y ejecutaría otros comandos.

Entonces, cada vez que necesite un procesador de comandos, use bash. Ejecutas comandos unix y los controlas.

ACTUALIZACIÓN después de 7 años (marzo de 2019)

Si bien la parte principal de mi respuesta no cambió, me gustaría señalar eso.

Bash también es un poderoso lenguaje de scripting. Para el procesamiento de texto podría ser una elección legítima absoluta.

Por favor, lea los comentarios de mkaito a continuación. Todos son completamente ciertos.

bakytn
fuente
1
El subconjunto de scripts de Bash tiene el mismo propósito general que cualquier lenguaje de scripts de propósito general. Agregue programas generales como sed en la mezcla, y estará cubierto por el 90% de todas las necesidades de scripts que tendrá.
mkaito
1
bash es un procesador de comandos para su poder es ejecutar otros comandos UNIX y programas en su scripts.like mencionaste SED etc. Él está pidiendo al elegir cierto lenguaje
bakytn
1
El shell es un iniciador de programas glorificado, pero sus capacidades de script están mucho más allá de eso. Le sugiero que aprenda algunas secuencias de comandos de shell reales.
mkaito
Puedo dormir en el suelo pero prefiero hacerlo en una cama. Los idiomas no se pueden comparar, tienen diferentes propósitos.
bakytn
2
Bueno, si Bash es el piso, algo como Haskell debe ser un
clavo
1

Los scripts de shell como bash, ksh, zsh, sh y fish son notoriamente sorprendentes, en comparación con los lenguajes de propósito general de alto nivel como Ruby, Python o Perl. Si bien un script de shell puede comenzar su vida como un archivo más corto que el script de propósito general equivalente, las sorpresas conducen a un montón de código de ajuste defensivo, como set -euo pipefailhabilitar modos estrictos.

Por ejemplo, la mayoría de los lenguajes de shell continúan ejecutando líneas en un script de shell, incluso cuando falla uno de los comandos. Por el contrario, un lenguaje de propósito general falla inmediatamente en el primer error y, a menudo, con carga, lo que resulta en un comportamiento más seguro y predecible en secuencias de comandos de complejidad incluso ligera.

mcandre
fuente
1

Artículo muy sesgado.

No creo que bash sea tan difícil de depurar. Python es a menudo demasiado rígido, mientras que bash te permite ser muy creativo. Si eres un buen pensador listo para usar, te gustará la fiesta.

Ejecuto scripts de bash en millones de lecturas de secuenciación de ADN en miles de archivos, y me sirve muy bien. Y al contrario de lo que todos dicen, las mismas versiones de los scripts en C ++ en realidad no se ejecutan mucho más rápido (en unos minutos los separan).

Creo que bash, como perl, no es el más fácil de usar / fácil de leer. Eso asusta a la gente porque la mayoría de las personas no son grandes pensadores abstractos. Pero los programadores más creativos y brillantes tienden a amarlo y a usarlo con frecuencia. Si te conoces a ti mismo y sabes que tienes cerebro, no te asustes con bash. Si eres un pensador básico, quizás te quedes con algo como Python. A cada cual lo suyo.

CK
fuente
0

Del "Libro de la Llama"

Perl intenta llenar el vacío entre la programación de bajo nivel (como en C o C ++ o ensamblaje) y la programación de alto nivel (como la programación "shell" [por ejemplo, bash]). La programación de bajo nivel suele ser difícil de escribir y fea, pero rápida e ilimitada; Es difícil superar la velocidad de un programa de bajo nivel bien escrito en una máquina determinada. Y no hay mucho que no puedas hacer allí. La programación de alto nivel, en el otro extremo, tiende a ser lenta, difícil, fea y limitada; Hay muchas cosas que no puede hacer con la shell o la programación por lotes si no hay un comando en su sistema que proporcione la funcionalidad necesaria. Perl es fácil, casi ilimitado, mayormente rápido y feo.

Geremia
fuente
0

Como regla general, use el lenguaje más simple que tenga un rendimiento suficientemente bueno para su tarea en cuestión. Y sus particularidades solo en la medida en que son realmente útiles.

Y sobre la legibilidad, Bash es horrible si tu estilo de programación es horrible. Si solo arrojas código allí, se vuelve oscuro.

Pero si divide el código en las funciones más cortas y nombra las cosas de una manera simple y comprensible, es el lenguaje más claro que puede encontrar. Porque es muy conciso.

Como muestra, este es mi último código en Bash. Observe lo fácil de entender y escribir es:

#! /bin/bash


mainFunction () {
    file="${1}"

    checkFile "${file}"
    executeFile "${file}"
}


changeToThisProgramDir () {
    cd "$( dirname "${BASH_SOURCE[0]}" )"
}


checkFile () {
    file="${1}"

    checkFileNotEmpty "${file}"
    checkFileExist "${file}"
    checkFileIsExe "${file}"
}


checkFileExist () {
    file="${1}"

    if [ ! -f "${file}" ]; then
        echo "The file doesn't exist: ${file}" >&2
        echo "If the name was correct either type: exeCute \"pathToYourExeFile\""
        echo "Or just open with exeCute from the file manager"
        exit 1
    fi
}


checkFileIsExe () {
    file="${1}"
    mime=$(fileMime "${file}")

    if [ "${mime}" != "application/x-dosexec" ]; then
        echo "Not an exe: ${file}" >&2
        exit 1
    fi
}


checkFileNotEmpty () {
    file="${1}"

    if [ "${file}" == "" ]; then
        echo "No file specified" >&2
        echo "Either type this: exeCute \"pathToYourExeFile\""
        echo "Or just open with exeCute from the file manager"
        exit 1
    fi
}


execute () {
    function="${1}"
    command="${2}"
    error=$(eval "${command}" 2>&1 >"/dev/null")

    if [ ${?} -ne 0 ]; then
        echo "${function}: ${error}" >&2
        exit 1
    fi
}


executeFile () {
    file="${1}"
    type=$(fileType "${file}")

    if [ "${type}" == "MS-DOS executable" ]; then
        execute "executeFile" "dosbox \"${file}\" -forcescaler normal2x -exit -fullscreen"
    else
        execute "executeFile" "wine \"${file}\""
    fi
}


fileMime () {
    file="${1}"

    attributes=$(file --brief --mime "${file}")
    IFS=";" read -r -a attributes <<< "${attributes}"
    echo "${attributes[0]}"
}


fileType () {
    file="${1}"

    attributes=$(file --brief "${file}")
    IFS="," read -r -a attributes <<< "${attributes}"
    echo "${attributes[0]}"
}


changeToThisProgramDir
mainFunction "${@}"
Alberto Salvia Novella
fuente