Quand utiliser Bash et quand utiliser Perl / Python / Ruby? [fermé]

78

Nous faisons tous nos scripts avec Bash jusqu'à présent, mais je commence à me sentir un peu ridicule. Bien que nous puissions bien sûr faire tout ce que nous voulons avec Bash (c'est assez puissant), je commence à me demander si nous ne devrions pas utiliser un langage de script approprié (dans notre cas, probablement Ruby).

Comment décidez-vous quand utiliser Perl / Python / Ruby sur Bash pour un script? Je ne pense pas qu'un script init avec Ruby ait du sens, mais qu'en est-il d'un script légèrement plus long qui ajoute des comptes de messagerie?

futlib
la source
1
Si vous pouvez le faire en utilisant l'un ou l'autre, est-ce vraiment important? Le choix n’est intéressant que si le script résultant présente des différences. Par exemple, le temps d'exécution peut être très différent (le problème ne se pose pas avec les comptes de messagerie).
Dennis

Réponses:

44

Étant donné un problème que les deux peuvent gérer, vous voudrez utiliser celui avec lequel vous êtes le plus à l'aise. En fin de compte, il y a beaucoup de petits détails et seule l'expérience peut vous apprendre à les voir.

Bash est un langage de script à usage général, tout comme Python, Ruby, Perl, mais chacun a des points forts différents. Perl excelle en analyse de texte, Python prétend être le plus élégant du groupe, les scripts Bash sont excellents en "piping stuff around", si vous voyez ce que je veux dire, et Ruby ... eh bien, Ruby est un peu spécial dans beaucoup de façons.

Cependant, les différences entre eux ne comptent vraiment que lorsque vous avez une bonne expérience de scripting à votre actif. Je vous suggère de choisir une langue et de la pousser à la limite avant de passer à la suivante. Vous pouvez faire beaucoup dans un script shell, plus que la plupart des gens ne l’admettraient. Toute langue est aussi difficile que vous le souhaitez. Après avoir écrit quelques mots, chaque langue est "facile" pour vous.

Être familiarisé avec le shell rapporte rapidement si vous habitez sous Linux, alors vous voudrez peut-être commencer par cela. Si vous trouvez une tâche impossible ou peu pratique à résoudre dans un script shell, utilisez autre chose.

De plus, gardez à l'esprit que l'apprentissage des scripts shell est très simple. Le véritable pouvoir de ce logiciel réside dans d’autres programmes, tels que awk, sed, tr, et al.

Mkaito
la source
Comme Ruby, je connais assez bien les scripts bash, mais parfois, je ne sais toujours pas quoi utiliser. Choisir en fonction de ses préférences personnelles à ce moment-là semble ridicule. Mais vous avez raison, je vais me demander ce que je veux faire et choisir le meilleur outil pour le poste.
Futlib
Personnellement, je vais utiliser une échelle de langages que je connais bien, par ordre croissant de complexité et de puissance, et utiliser le plus simple qui conviendra. Mais en réalité, le seul moyen de savoir avec certitude consiste à écrire votre script dans toutes les langues et à comparer le résultat. C'est plus un sentiment d'intestin qu'une certitude. Après quelques années à écrire des scripts, vous aurez rencontré la plupart des "types de problèmes" et vous saurez quelle langue les a bien résolus.
mkaito
Je voulais juste ajouter que, en utilisant de petits programmes dans le paquet GNU coreutils (comme tr, sort, uniq) et en les lissant, il est possible d'accomplir beaucoup de tâches.
GMaster
58

TL; DR - utilisez bash uniquement pour installer une meilleure langue (si elle n’est pas déjà disponible), sinon vous perdez un temps précieux et irrécupérable. Si vous ne pouvez pas le faire manuellement sur la ligne de commande sans commettre d'erreur, n'écrivez pas avec bash / shell.

Nous sommes en 2015, je considérerais donc ce qui suit:

  1. surcharge de mémoire

    • La surcharge de la mémoire d'exécution de Ruby / Python par rapport à bash est minime (à cause des bibliothèques partagées), alors qu'il est probablement impossible de gérer un script bash non trivial (c'est-à-dire avec plus de 100 lignes) - l'utilisation de la mémoire n'est donc pas un facteur.
  2. le temps de démarrage

    • Le démarrage de Ruby / Python est peut-être un peu plus lent, mais il est peu probable que vous exécutiez beaucoup de processus Ruby / Python complets dans une boucle serrée 100 fois par seconde (si vous avez ce genre de besoins, bash / shell est de toute façon, vous aurez probablement besoin de passer en C / C ++)
  3. performance

    • presque tous les traitements de données typiques seront plus rapides en Ruby / Python - ou du moins comparables (ou, vous avez besoin de C / C ++ / Haskel / OCaml / peu importe de toute façon)
    • la performance réelle / le goulot d'étranglement dans l'exécution (ou même la productivité) ne sera presque jamais "un manque d'utilisation de bash / shell" (même le tiret Ubuntu pour le démarrage montre à quel point bash est le problème - et une busybox est probablement le seul cas d'utilisation , parce qu'il n'y a rien de plus que « bash » et « vi » pour écrire et exécuter du code, et il n'y a souvent aucun moyen d'ajouter / télécharger ou stocker de quoi que ce soit d' autre)
    • Exécuter d'autres processus pour faire le travail (comme sed / awk / grep) est en réalité d'une ampleur inférieure à celle d'appeler une méthode sur un objet actif en mémoire
  4. productivité

    • il est trop facile de faire des erreurs dans Bash / shell par rapport à l'utilisation de "vraies" méthodes, paramètres, variables et exceptions en Ruby / Python
    • Agile est la norme, alors que Bash ne la prend pas en charge (manque de capacités de tests unitaires, de bibliothèques, d’OO, de modularité, de peluches, d’introspection, de journalisation, de métaprogrammation; il est presque impossible de refactoriser sans casser quelque chose).
    • Beaucoup trop d'incompatibilités avec d'autres shells, des variables d'environnement mineures peuvent complètement casser un script (et certains outils de développement importants tels que Puppet ignorent les lignes shebang et transmettent ou réécrivent des variables de shell importantes), tandis que Ruby / Python a une migration relativement bien définie. chemins même pour les changements de version majeurs
    • L'apprentissage d'une nouvelle langue prend une fraction du temps nécessaire au débogage de scripts shell en raison de problèmes spécifiques à celui-ci (notamment - noms de variables, pas de booléens, pas d'exceptions, etc.)
    • même les scripts de démarrage sont une mine terrestre (en particulier parce qu'ils peuvent échouer lors du démarrage du système ), et étant donné les failles de sécurité récentes de bash, il vaut peut-être mieux utiliser un C clair (avec de bonnes bibliothèques) - oui, C a besoin d'être compilé, configuré, etc. , mais même un simple script shell peut nécessiter un référentiel, puis la gestion des versions, puis la mise en package de toute façon.
    • Tout ce qui est disponible avec sed / awk / grep est probablement déjà intégré à Ruby / Python - sans que cela soit une dépendance ou des "différences" entre les versions de ces outils sur toutes les plates-formes (que faire si cela fonctionne dans votre configuration)
  5. la sécurité d'emploi
    • à quoi sert-il d'obtenir un emploi que vous n'aimez pas? (sauf si vous aimez passer toutes ces heures difficiles à déboguer mais simples à créer des bogues de script shell)

Je trouve qu'il n'y a aucune raison d'utiliser Bash / Shell si vous avez installé Ruby / Python.

Et probablement, obtenir Ruby / Python installé n'a même pas besoin d'un script bash (à l'exception de busybox, certains outils système dépendent de la présence de Python / Perl de toute façon).

Et chaque fois que vous écrivez un script shell, vous "pratiquez" exactement ce que vous faites - au lieu d'apprendre quelque chose de plus puissant / productif.

Pourquoi les gens utilisent-ils Bash de nos jours? Parce que c'est une habitude terrible et difficile à rompre. Un script est rarement "fini pour toujours" après les premières minutes - peu importe à quel point les gens ont tendance à penser ainsi. Avec l'erreur "c'est le dernier bogue de ce script".

Conclusion: utilisez bash / shell uniquement lorsque vous êtes absolument obligé (par exemple ~/.bashrc, busybox), car ce n'est presque jamais "le bon outil pour le travail" de nos jours.

Cezary Baginski
la source
28

J'utilise bash lorsque mon objectif principal est la gestion de fichiers. Cela peut inclure le déplacement, la copie et le changement de nom de fichiers, ainsi que l'utilisation de fichiers en tant qu'entrée pour d'autres programmes ou le stockage de la sortie d'un autre programme dans des fichiers. J'écris rarement du code bash qui examine réellement le contenu d'un fichier ou génère la sortie à écrire dans un fichier; Je laisse cela aux autres programmes (que je peux écrire en Perl ou en python) que je lance via bash.

J'utilise Perl et Python lorsque mon objectif principal est de lire des données à partir de fichiers, de les traiter d'une manière ou d'une autre et d'écrire les résultats dans des fichiers. Si je me retrouve à utiliser (en Perl) la systemcommande, les ticks arrière ou (en python) le subprocessmodule trop en profondeur, je considère écrire le script en bash. D'un autre côté, je commence parfois à ajouter tellement de fonctionnalités à un script bash qu'il est finalement plus logique de les réécrire en Perl / python plutôt que de gérer le support limité (par comparaison) de bash pour la portée, les fonctions, les structures de données, etc. .

Chepner
la source
2
J'ai aussi utilisé le cautionnement sur Bash chaque fois que la lecture de fichier / la génération de texte était requise, mais après avoir appris l' =~opérateur soutenu par, [[ ]]je
m'aimais bien
16

J'aime les critères énoncés dans cet article de blog .

  • S'il n'y a pas d'arguments à transmettre, c'est probablement un script shell.
  • S'il n'y a pas beaucoup de choses pour la logique de contrôle (à part une boucle ou si / sinon), c'est probablement un script shell.
  • Si la tâche consiste à automatiser les instructions de ligne de commande, il s’agit presque certainement d’un script shell.
MarkTee
la source
8

J'ai trouvé cette analyse Perl versus Bash utile ...

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

Pour plus de commodité, je copie un résumé de l'auteur 1) lorsque bash est meilleur résultat et 2) quand perl est meilleure conclusion ...

Quand bash va mieux ...

  • Echec du travail
  • Commandes à la sortie
  • Traitement des lignes de sortie
  • Ici les documents
  • Équivalences de fichiers
  • Comparaisons d'horodatage de fichier
  • Expansion Tilde

Quand Perl va mieux ...

Perl bat toujours la merde de bash pour la plupart des applications. Les raisons pour lesquelles je pourrais préférer Perl incluent (mais ne sont pas limitées à):

  • Ça va être plus rapide. Principalement parce que je n'ai pas réellement besoin de démarrer de nouveaux processus pour beaucoup des choses que je veux faire (basename et dirname étant les exemples les plus évidents, mais généralement couper, grep, trier et wc peuvent également être éliminés).
  • La gestion des cordes à bash est au mieux rudimentaire, et tout ce qui concerne $ IFS est super-maladroit.
  • Les conditions dans les scripts de shell peuvent être mauvaises.
  • Citer dans des scripts shell peut être un cauchemar.
  • La déclaration de cas de bash laisse beaucoup à désirer au-delà des cas simples (NPI).
  • Les tableaux en bash sucer. Les hachages dans bash (en supposant que votre bash soit suffisamment récente pour les avoir du tout) sont encore plus difficiles à sucer.
  • Une fois que le traitement des fichiers ou de la sortie de la commande dépasse le cas simple que j'ai énuméré ci-dessus, Perl commence vraiment à fumer.
  • CPAN.

Donc, ce n'est pas comme si bash allait bientôt prendre le relais de Perl. Mais je trouve toujours, après toutes ces années, qu’un simple script shell peut parfois être plus simple qu’un simple script Perl. Comme je le dis, je salue toutes les tentatives de me convaincre du contraire. Mais, encore une fois, il n’ya rien de mal à avoir quelques outils différents dans votre boîte à outils.

buzz3791
la source
Fait intéressant, dans Ruby, tous les points (?) Ne s'appliquent pas, car Ruby a at_exit (), realpath (), expand_path (), stat (), heredocs et exceptions ( fail "error" unless system("foobar")).
Cezary Baginski
5

D'après mon expérience, bash versus python est un compromis entre temps de développement et flexibilité. Une solution rudimentaire à un problème peut généralement être établie dans un script bash plus rapidement que dans un script python.

Python aura tendance à vous faire réfléchir davantage sur la structure de votre solution que le script bash équivalent. Python a plus de pouvoir expressif qu'un script bash et a donc tendance à évoluer et à mieux se modifier avec le temps. Il reste aussi plus lisible en général.

Bash est plus proche du système de fichiers et peut s'avérer très utile pour les premières ébauches de solutions à des problèmes qui ne sont PAS bien définis. Pour cette raison, un script bash pourrait être un bon choix pour prototyper quelque chose avec l'intention de le porter en python une fois que le problème sera mieux compris.

Travis
la source
4

Bash est un shell Unix qui comprend un langage de script. C'est plutôt un processeur de commande. vous contrôlez la façon dont vous exécutez les commandes, vous les exécutez réellement.

Perl / Ruby / Python sont des langages à usage général.

Quand vous voulez un script shell, vous utilisez Bash

Si vous voulez une tâche plus complexe ou sans rapport avec le shell. Utilisez Python etc.

Je ne comparerais jamais ces langues en réalité. Python etc. sont portables. Vous pouvez les exécuter n'importe où. Bash est uniquement pour Unix.

Python, etc. ont des tonnes de bibliothèques réutilisables qui résolvent des millions de tâches.

C'est presque pareil si vous le demandez. "Quand utiliser Paint et quand utiliser Photoshop"

Pour le traitement des courriels, j’utiliserais encore Ruby, car il contient de nombreuses bibliothèques réutilisables.

Mais le meilleur moyen serait de combiner bash et rubis. Ce serait juste. De la même manière que vous créez un script de traitement de courrier électronique en ruby ​​et en script bash, ce script ruby ​​est appelé et les autres commans exécutés.

Donc, chaque fois que vous avez besoin d'un processeur de commande, vous utilisez bash. Vous exécutez des commandes unix et les contrôlez.

MISE À JOUR après 7 ans (mars 2019)

Bien que l'essentiel de ma réponse n'ait pas changé, je voudrais le souligner.

Bash est également un puissant langage de script. Pour le traitement de texte, cela pourrait être un choix légitime.

S'il vous plaît lire les commentaires de mkaito ci-dessous. Ils sont tous complètement vrais.

Bakytn
la source
1
Le sous-ensemble de scripts de Bash est aussi utile que tout langage de script à usage général. Ajoutez à cela des programmes généraux tels que sed et vous obtiendrez une couverture de 90% des besoins en script que vous aurez jamais.
mkaito
1
bash est un processeur de commande, il a donc le pouvoir d'exécuter d'autres commandes et programmes unix dans leurs scripts. Comme vous l'avez mentionné sed, etc. Il demande quand choisir une certaine langue.
bakytn
1
Le shell est un lanceur de programme glorifié, mais ses capacités de script vont bien au-delà. Je suggère que vous appreniez de vrais scripts shell.
mkaito
Je peux dormir par terre mais je préférerais le faire sur un lit. Les langues ne peuvent pas être comparées, elles ont des objectifs différents.
bakytn
2
Eh bien, si Bash est la parole, quelque chose comme Haskell doit être une planche à ongles :-)
mkaito
1

Les scripts shell tels que bash, ksh, zsh, sh et fish sont notoirement surprenants, comparés aux langages généraux de haut niveau tels que Ruby, Python ou Perl. Alors qu'un script shell peut commencer sa vie comme un fichier plus court qu'un script générique équivalent, les surprises conduisent à de nombreux codes d'habillage défensifs, set -euo pipefailpermettant par exemple d'activer des modes stricts.

Par exemple, la plupart des langages shell continuent à exécuter des lignes dans un script shell, même en cas d'échec d'une des commandes. En revanche, un langage polyvalent échoue immédiatement à la première erreur et souvent de manière très lourde, ce qui entraîne un comportement plus sûr et plus prévisible dans les scripts même de complexité légère.

mcandre
la source
1

Article très biaisé.

Je ne trouve pas que bash soit si difficile à déboguer. Python est souvent beaucoup trop rigide, alors que bash vous permet d’être très créatif. Si vous êtes un bon penseur prêt à l'emploi, vous aimerez bash.

J'exécute des scripts bash sur des millions de lectures de séquençage d'ADN dans des milliers de fichiers, et cela me convient parfaitement. Et contrairement à ce que tout le monde dit, les mêmes versions des scripts en C ++ ne s'exécutent pas beaucoup plus rapidement (séparez-les en quelques minutes).

Je pense que bash, comme Perl, n’est pas le plus convivial / facile à lire. Cela effraie les gens parce que la plupart des gens ne sont pas de grands penseurs abstraits. Mais les programmeurs les plus brillants et les plus créatifs ont tendance à l’aimer et à en faire un usage fréquent. Si vous vous connaissez et savez que vous avez un cerveau, ne soyez pas effrayé par bash. Si vous êtes un penseur de base, gardez peut-être quelque chose comme Python. A chacun ses goûts.

CK
la source
0

Du "Livre des lamas"

  • Randal L. Schwartz, Tom Phoenix et Brian D. Foy, Learning Perl (Sébastopol, CA: O'Reilly, 2011), ch. 1.2 "Que signifie Perl?" , §§ "Pourquoi Larry [le créateur de Perl] n'a-t-il pas utilisé une autre langue?", P. 5:

Perl essaie de combler le fossé entre la programmation de bas niveau (telle que C ou C ++ ou l’assemblage) et la programmation de haut niveau (telle que la programmation «shell» [par exemple bash]). La programmation de bas niveau est généralement difficile à écrire et laide, mais rapide et illimitée; il est difficile de battre la vitesse d'un programme bien écrit de bas niveau sur une machine donnée. Et il n'y a pas grand chose que tu ne puisses pas faire là-bas. La programmation de haut niveau, à l'autre extrême, a tendance à être lente, dure, laide et limitée; Il y a beaucoup de choses que vous ne pouvez pas faire du tout avec la programmation shell ou batch si aucune commande sur votre système ne fournit les fonctionnalités nécessaires. Perl est facile, presque illimité, la plupart du temps rapide et un peu moche.

Gérémie
la source
0

En règle générale, utilisez le langage le plus simple et suffisamment performant pour votre tâche. Et ses particularités seulement dans la mesure où elles sont vraiment utiles.

Et en ce qui concerne la lisibilité, Bash est horrible si votre style de programmation est horrible. Si vous jetez simplement du code là-bas, il devient obscur.

Mais si vous divisez le code en fonctions les plus courtes et que vous nommez les choses d'une manière simple et compréhensible, c'est le langage le plus clair que vous puissiez trouver. Parce que c'est très laconique.

Comme spécimen, ceci est mon dernier code dans Bash. Notez à quel point il est facile à comprendre et à taper:

#! /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
la source