Remplacer sed, awk, cut et Perl par Python (= orgasme pour sysadmin) 27


La force de Perl c’est qu’il permettait de piper des données directement via la ligne de commande pour faire des manipulations rapides.

C’est pour cela que c’était devenu les choix des sysadmins. Parce que jusqu’ici, le choix c’était soit de faire un truc simple en connaissant par coeur la tool box GNU, soit ouvrir un fichier et faire un script.

Python ne permet pas de piper des données directement dans la commande, mais des projets ont vu le jour pour le faire.

Il y a le projet pyp, que l’on doit à Sony Pictures Imageworks qui avait besoin de se simplifier l’automatisation des tâches de build pour ses films.

Et il y a pyped, dont j’avais brièvement parlé ici (article qui mérite d’être mis à jour vu que j’ai remplace dateutils par arrow).

Les deux étaient sympas, mais avait des syntaxes alambiquées, n’étaient pas compatibles python 3 et manquaient d’imports auto. Cependant, pyped est récemment passé en v1.0, donc stable, et a une toute nouvelle approche de syntaxe qui rend la bestiole super agréable à utiliser.

Présentation.

Stdin, ligne à ligne

L’installation est bateau, c’est du pip :

pip install --user pyped

Et derrière, on obtient la commande pyp. Elle s’utilise essentiellement à la suite d’une autre commande. Typiquement :

cat /etc/fsta | pyp "un truc"

L’astuce, c’est que “un truc” peut être n’importe quelle expression Python. Généralement une expression qui print() quelque chose.

Or, Pyped met automatiquement à disposition de cette expression deux variables :

  • La ligne en cours, dans la variable x.
  • Le numéro de la ligne en cours, dans la variable i.

L’expression Python est appelée une fois pour chaque ligne.

Par exemple, supposons que j’ai un fichier “fortune.txt” contenant :

bitcoin (btc) : 5
euros () : 100
dollars ($) : 80

Si je veut tout mettre en majuscule, je fais :

$ cat fortune.txt | pyp "print(x.upper())"
BITCOIN (BTC) : 5
EUROS () : 100
DOLLARS ($) : 80

On peut mettre plusieurs expressions d’affilé. Ainsi, si je veux récupérer la somme et le symbole uniquement :

$ cat fortune.txt | pyp "devise, sign, _, value = x.split()" "sign = sign.strip('()')" "print('%s%s' % (value, sign))"
5btc
10080$

Ok, c’est plus long que perl, mais vachement plus facile à écrire et à relire. Et j’utilise un langage que je connais déjà. Et pas besoin de faire un mix incompréhensible de sed, awk et autre cut.

Si j’ai vraiment besoin de lisibilité, je peux même le mettre sur plusieurs lignes :

$ cat fortune.txt | pyp "                                                                                                 
devise, sign, _, value = x.split() 
sign = sign.strip('()') 
print('%s%s' % (value, sign))  
"
5btc
10080$

Vous aurez noté que j’utilise print() et que je semble ne pas me soucier de l’unicode. C’est parceque pyped fait ça au début du script :

from __future__ import print_function, unicode_literals, division, absolute_imports

Du coup, on est bien en Python 2.7, mais on bénéficie de la division améliorée, de la fonction pour printer, des imports absolus et surtout, de l’unicode partout. D’ailleurs pyped vous transforme x pour que ce soit un objet unicode.

Dans tous les cas, pyped est compatible Python 3.

Tout traiter d’un coup

Parfois, on a besoin d’avoir accès à toutes les lignes, pas juste les lignes une à une. pyped permet cela avec l’option -i. Les variables x et i disparaissent au profit de la variable l, qui contient un itérable sur toutes les lignes.

Par exemple, envie de trier tout ça ?

cat fortune.txt | pyp -i "
lignes = (x.split() for x in l)
lignes = sorted((v, s.strip('()')) for d, s, _, v in lignes)
for ligne in lignes: print('%s%s' % ligne)
"
100€
5btc
80$

Moar options

Lisez la doc, car il y a d’autres options du genre éviter que pyped vous strip automatiquement le ligne break, forcer l’encoding, etc.

Parmi les trucs les plus utiles, il y a l’option -b qui permet de lancer un code avant la boucle. Pratique pour importer des trucs genre le module tarfile pour extraire une archive avant d’utiliser son contenu.

Néanmoins la plupart du temps on a rien besoin d’importer car pyped importe déjà automatiquement les modules les plus utiles : maths, datetime, re, json, hashlib, uuid, etc.

27 thoughts on “Remplacer sed, awk, cut et Perl par Python (= orgasme pour sysadmin)

  • Erik

    Alors oui mais non ! Si Perl est devenu populaire, c’est pour plusieurs raisons. C’est vrai qu’on ne refuse jamais un(e) petit(e) pipe le matin en arrivant au bureau, mais Perl avait d’autres qualités notables.

    Le contexte de liste, qu’on retrouve dans l’unpacking de Python ou qu’on pouvait salement reproduire dans les autres langages avec des astuces de sioux (string avec séparateur, muhahahahAHAHAHA).

    Les Regex.

    La communauté d’entraide (Perl monks, CPAN)

    Tout simplement, un langage spécialisé pour le reporting en entreprise à une époque où tout le monde utilisait du fichier plat.

    Typage faible des variables et transtypage automatiquement géré par le contexte. Ce qui permettait aux programmeurs du dimanche de ne pas s’embêter avec la rigueur de déclaration/conception d’autres langages.

    Tableaux associatifs ohmygaude!

    Et puis quand tu lis ton bouquin O’Reilly “Programming Perl” au pieu à coté de ta nana, tu pleures d’émotion devant la beauté des utilisations de ce langage, révélant ainsi la sensibilité qui sommeille au fond de toi. Et là, ta nana qui regardait un film de filles pleure avec toi et vous vous endormez dans les bras l’un de l’autre *sniff* c’est beau.

    …et puis “sed”, “awk”, et “cut” tu ne les apprends pas. Tu vas juste faire une recherche google pour voir comment ça marche et faire une commande spéciale 1 fois tous les 10 ans.

  • kontre

    @Erik: t’es en train de dire que perl était génial il y a 20 ans, ce qui n’est pas le propos de l’article (enfin que dans l’intro, quoi). Mais j’ai l’impression que grooso modo tout ce que tu cites se retrouve dans python. Donc aujourd’hui, pyped a toutes ces qualités et est lisible. What else ?

  • Sam Post author

    On est pas la pour se battre. Perl a été pionier, il faut pas lui retirer ça.

  • Deimosfr

    on oublie les perfs par contre. Python est pas connu pour sa rapidité mais pour sa souplesse. Et contre des binaires en C ou du Perl…y’a pas photo. Le concept est sympas mais je suis trop accroché aux bonne vielles commande dispo sur n’importe quelle distro.

  • Sam Post author

    Des perfs pour du one liner ? Je doute qu’il y ait un quelconque travail de sysadmin pour lequel python soit trop lent de toute manière.

  • cym13

    +1 pour les perf, le plus cher pour un sysadmin c’est le coût humain en développement et maintenance, pas le coût en temps d’execution.

    Par contre, autant j’aime bien tout ces petits outils, autant je me sens à chaque fois mal parce que je sais que je ne les utiliserai pas. On peut faire tout le reproche que l’on veut à cut, sed, awk et compagnie mais ils présentent une assurance de portabilité. Une des raisons pour lesquelles j’apprécie la ligne de commande c’est qu’elle est dans une grande mesure indépendante du système sur lequel elle tourne : sa stabilité permet une rapidité de mise en œuvre sans équivalent.

  • Sam Post author

    La portabilité ici n’a aucun interêt pour moi. Je vais pas faire un script avec ça. Si je dois faire un script, je vais le faire en Python.

    J’utilise py pour tous ces one liners dont j’ai besoin : supprimer certains fichiers, filtrer le contenu de logs, renommer à la volée, etc. Et pour ça, la portabilité n’a pas de sens, car c’est toujours du one shot. A l’inverse, je note que je trouve toujours plus rapidement une solution en Python qu’en bash dès que je veux traiter une donnée, donc ça m’aide.

  • cym13

    Par portabilité j’entendais portabilité des compétences, pas du code, mais j’entend ce que tu veux dire.

  • LLM

    Heu…. Le beau préjugé sur les sysadmin…

    Genre “tu t’en fous des perfs de tes scripts”. Quand vous aurez à gérer des serveurs dispos 24/7 partout dans le monde, vous ne pourrez pas vous permettre d’utiliser les CPU pendant 4 heures “parce que personne n’utilise le serveur”…

    Du coup Python est largement inadapté dans ce cas. Et si un système est inadapté dans un cas, il est inadapté dans tous les cas : on ne va pas multiplier les compétences inutilement : soit ça remplace tout et c’est très bien, soit ça remplace rien et ça n’a qu’un intérêt pour la curiosité.

    Si vous utilisez ça sur vos serveurs alors que vous n’êtes pas sysadmin, très bien hein, ce sont vos serveurs où Python est déjà installé, et vous n’avez aucun intérêt à avoir des compétences en la matière, ce qui est normal.

    Mais prétendre que ça va remplacer sed, awk, cut et perl et qu’en plus ça va donner des orgasmes aux sysadmin : la blague !

    M’enfin, des bisous quand même…

  • Sam Post author

    D’abord, tu confonds deux choses: pyped et les perfs de Python en script.

    La première, rien à voir avec des perfs, c’est pour des one-liners dans le shell, pas pour des scripts. On est donc hors de propos.

    Le seconde, ce sont les perfs de Python en général. Et là, comme ça a déjà été répété 100 fois, les perfs se mesurent toujours relativement à un besoin. Or, pour le besoin d’un sysadmin, les perfs de Python sont 100 fois suffisante.

    Je te mets au défi de me donner une tâche de sysadmin courante pour laquelle les perfs de Python ne sont pas pertinentes. Chiffre à l’appui, incluant l’équivalant en perl, bash, et le temps pour les coder.

    J’attends.

  • LLM

    Ça fera 700€ (bah ouais, je bosse pas gratuitement).

    Je rebondissais essentiellement sur le “orgasme pour sysadmin”. Il ne faut pas penser que l’Autre désire forcément la même chose que soi. C’est déjà présomptueux et c’est en plus totalement égoïste.

    Je suis sysadmin, et l’article m’en touche une sans faire bouger l’autre. Pourquoi ?

    – je ne vais pas installer Python pour des process déjà exécutés et donc pas convertir mes scripts ;
    – je ne vais pas installer Python sur 250 serveurs ;
    – je ne vais pas installer Python sur des serveurs ne nécessitant pas Python car on n’installe pas un programme superflu alors que d’autres systèmes, fournis de base, font le même job (genre, tsé, réduire la surface d’exposition, tout ça) ;
    – la documentation pour un sysadmin concernant sed, awk, cut et perl est bien plus fournie que la documentation du système proposé dans l’article ;
    – la communauté des sysadmin utilisant les programmes de base > la communauté des sysadmin utilisant Python ;
    – je ne vais pas changer mon système de monitoring pour qu’il aille récupérer ses infos via Python ;
    – je ne vais pas refaire mes images systèmes pour y inclure Python ;
    – mes scripts correspondent déjà au besoin et s’exécutent dans un temps record sans Python.

    En bref, il ne suffit pas de s’atteler au pipe pour faire jouir un sysadmin, il faut aussi s’occuper de tout le contexte.

    Après, que l’astuce serve à un dev Python qui s’occupe d’un serveur ou à un sysadmin qui gère un parc de serveurs Python, je veux bien.

    M’enfin de là à remplacer sed, awk, cut et perl… Je sais que quand on a un marteau, tous les problèmes sont des clous, mais faudrait voir à redescendre un peu sur Terre parfois. :)

    (je suis déçu parce qu’on me promet l’orgasme en titre et finalement j’ai même pas une demi-molle)

  • ZZelle

    En général python est déjà installé …

    Après, tout est question d’utiliser le bon outil en fonction du besoin et surtout de son expertise.
    Perso, 80% du temps grep/awk/sed suffise à mon besoin pour manipuler des grosses quantités de données.

    Quand ça devient trop compliqué, je copie mon script pyargs (pyp/pyped maison) et c’est parti en python pour les manips que je ne sais pas faire (simplement) autrement.

    Quand je dois manipuler des Gigas de logs (squid/fw) … j’évite python ou j’utilise le plus dans les pipes sinon ça prend 4 fois plus de temps … ce qui est génant quand on tourne autour des 5 minutes de traitement !

  • AlexP

    Lorsque le net sera enfin totalement codé en python les nouvelles générations pourront enfin redécouvrir les joies des anciens comme celle de disposer de connexions fibre mais d’avoir le débit d’un 56k.

    C’est ça l’évolution.

  • Sam Post author

    @LLM: la réponse a du style :) Mais le but n’est pas de remplacer tous tes scripts, seulement de se simplifier les one-liners. Tu extrapoles, là, on dirait mon ex.

    @ZZelle: Python traite des Go de Log très rapidement. Il faut juste le faire avec des générateurs, pas en chargeant tout en mémoire.

  • ZZelle

    @sam : ce que je lance c’est un truc du genre de ce qui suit

    #!/usr/bin/python -u
    import sys
     
    for x in iter(sys.stdin.readline, ''):
        print x, # la, c un exemple simple :)
  • Sam Post author

    C’est pas cette partie là qui est lente à mon avis. Faudrait voir les scripts en entier ^^

    Bel usage du sentry d’ailleurs, sur stdin, c’est très malin.

  • Sam Post author

    iter prend un deuxième paramètre appelé ‘sentry’ qui arrête l’itérateur si il est rencontré.

  • jetenfule

    @LLM, si tu appliques ton argumentaire réactionnaire à l’informatique en général, aucune avancée n’est possible ?

    “Comment ça le C++ ?
    Tous mes programmes sont en C, j’ai toujours fait du C, je ne vois pas pourquoi je me ferai chier à apprendre un nouveau langage alors que l’autre m’assure compatibilité et universalité sur toutes les plateformes que j’utilise.”

    Je te laisse remplacer C++/C par bat/Powershell ou même VB/VBS.

    Merci, au revoir, bonne journée.

  • Ryzz

    Je me suis fait baisé par la commande py qui est passée à pyp:

    WARNING: since the last version the command line name “py” has been renamed to “pyp” to avoid conflict with the new tool in the Python stdlib named “py”. It means pyped is now incompatible with the “Python Power at the Prompt” project sharing the same name and goals.

  • Httqm

    @jetenfule : le changement pour le changement, c’est une façon de voir, mais je doute de son efficacité sur le long terme. Tu réécris tous tes logiciels dans tous les nouveaux langages dès qu’ils sortent juste pour être à la page, ou bien tu gardes ce qui existe et qui fonctionne correctement ?

    @LLM : +1
    Plus j’utilise sed / awk / cut / perl et compagnie et mieux je me rends compte de la puissance de ces outils. On les utilise d’ailleurs souvent très mal.
    Donc si on peut faire de même avec Python, tant mieux (avoir le choix des outils est une bonne chose), mais je préfère garder mes petits outils du shell, merci :-)

  • Sam Post author

    Tout ce que je constate, c’est que je prends 10 secondes pour obtenir le résultat avec pyped, et 10 minutes avec sed + awk + cut. Après je n’utilise pas perl, mais si on utilise perl, on a pas besoin de sed/awk/cut, et si on et pythoniste, on utilise python plutôt que perl.

  • nabellaleen

    Tiens, petite coquille au passage :

    lignes = (x.split() for x in l)

    devrait plutôt être

    lignes = (x for x in l.split())

  • nabellaleen

    Oups, oublie ce que j’ai dit, la coquille c’est moi … XD

  • Sebultura

    “Et pas besoin de faire un mix incompréhensible de sed, awk et autre cut.”

    Quand on fait des mix de sed, awk et cut, c’est qu’on ne sait pas utiliser awk ! :p

Leave a comment

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <pre> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Des questions Python sans rapport avec l'article ? Posez-les sur IndexError.