web-dev-qa-db-fra.com

Comment implémenter les idiomes bash communs en Python?

Je manipule actuellement mon fichier texte avec un groupe d’AWK, sed, Bash et un tout petit peu de Perl.

J'ai vu mentionné quelques endroits où python est bon pour ce genre de chose. Comment puis-je utiliser Python pour remplacer les scripts Shell, AWK, sed et copains?

242
Chris Jefferson

N'importe quel shell a plusieurs ensembles de fonctionnalités.

  • Les commandes essentielles Linux/Unix. Tous ces éléments sont disponibles via la bibliothèque sous-processus . Ce n'est pas toujours le meilleur choix en premier pour faire toutes les commandes externes . Regardez aussi shutil pour certaines commandes qui sont des commandes Linux distinctes, mais vous pourriez probablement les implémenter directement dans vos scripts Python. Un autre lot considérable de commandes Linux se trouve dans la - os bibliothèque, vous pouvez le faire plus simplement en Python.

    Et - bonus! -- plus vite. Chaque commande Linux séparée dans le shell (à quelques exceptions près) lance un sous-processus. En utilisant les modules Python shutil et os, _, vous ne créez pas de sous-processus.

  • Les fonctionnalités de l'environnement Shell. Cela inclut des éléments qui définissent l’environnement d’une commande (répertoire actuel, variables d’environnement et autres paramètres). Vous pouvez facilement gérer cela depuis Python directement.

  • Les fonctionnalités de programmation de Shell. Il s’agit de la vérification du code d’état du processus, des différentes commandes logiques (si, tant que, pour, etc.) de la commande de test et de tous ses parents. Les choses de définition de fonction. Tout cela est beaucoup plus facile en Python. C'est l'une des énormes victoires de se débarrasser de bash et de le faire en Python.

  • Caractéristiques d'interaction. Cela inclut l'historique des commandes et tout ce qui ne l'est pas. Vous n'en avez pas besoin pour écrire des scripts Shell. Ceci est uniquement pour l'interaction humaine, et non pour l'écriture de scénario.

  • Les fonctionnalités de gestion de fichiers Shell. Cela inclut la redirection et les pipelines. C'est plus compliqué. Une grande partie de cela peut être fait avec un sous-processus. Cependant, certaines choses faciles dans Shell sont désagréables en Python. Des choses comme (a | b; c ) | something >result. Ceci exécute deux processus en parallèle (avec la sortie de a en tant qu'entrée vers b), suivie d'un troisième processus. La sortie de cette séquence est exécutée en parallèle avec something et la sortie est collectée dans un fichier nommé result. C'est complexe à exprimer dans une autre langue.

Des programmes spécifiques (awk, sed, grep, etc.) peuvent souvent être réécrits en tant que Python. N'exagérez pas. Remplacez ce dont vous avez besoin et faites évoluer votre module "grep". commencez par écrire un module Python qui remplace "grep".

La meilleure chose à faire est que vous puissiez le faire par étapes.

  1. Remplacez AWK et Perl par Python. Laissez tout le reste seul.
  2. Envisagez de remplacer GREP par Python. Cela peut être un peu plus complexe, mais votre version de GREP peut être adaptée à vos besoins de traitement.
  3. Envisagez de remplacer FIND par Python) boucles utilisant os.walk. C'est une grande victoire car vous ne générez pas autant de processus.
  4. Essayez de remplacer la logique commune du shell (boucles, décisions, etc.) par Python).
144
S.Lott

Oui bien sûr :)

Jetez un coup d'œil à ces bibliothèques qui vous aident N'écrivez plus jamais de scripts Shell (devise de Plumbum).

En outre, si vous voulez remplacer awk, sed et grep par quelque chose Python basé, je recommande pyp -

"The Pyed Piper", ou pyp, est un outil de manipulation de texte en ligne de commande similaire à awk ou sed, mais qui utilise les méthodes standard python string et list ainsi que les fonctions personnalisées évoluées pour générer rapidement résulte dans un environnement de production intense.

103
Piotr Dobrogost

Je viens de découvrir comment combiner les meilleures parties de bash et ipython. Jusqu'à présent, cela me semble plus confortable que d'utiliser un sous-processus, etc. Vous pouvez facilement copier de grandes parties de scripts bash existants, par exemple. ajoute la gestion des erreurs de la manière python) :) Et voici mon résultat:

#!/usr/bin/env ipython3

# *** How to have the most comfort scripting experience of your life ***
# ######################################################################
#
# … by using ipython for scripting combined with subcommands from bash!
#
# 1. echo "#!/usr/bin/env ipython3" > scriptname.ipy    # creates new ipy-file
#
# 2. chmod +x scriptname.ipy                            # make in executable
#
# 3. starting with line 2, write normal python or do some of
#    the ! magic of ipython, so that you can use unix commands
#    within python and even assign their output to a variable via
#    var = !cmd1 | cmd2 | cmd3                          # enjoy ;)
#
# 4. run via ./scriptname.ipy - if it fails with recognizing % and !
#    but parses raw python fine, please check again for the .ipy suffix

# ugly example, please go and find more in the wild
files = !ls *.* | grep "y"
for file in files:
  !echo $file | grep "p"
# sorry for this nonsense example ;)

Voir la documentation IPython sur commandes du système et son utilisation en tant que système .

57
TheK

Depuis 2015 et Python 3.4, il existe maintenant un shell interactif relativement complet disponible à l'adresse suivante: http://xon.sh/ ou https://github.com/scopatz/xonsh

La vidéo de démonstration ne montre pas les canaux utilisés, mais ils sont pris en charge en mode Shell par défaut.

Xonsh ('conch') essaye très fort d'imiter bash, donc les choses pour lesquelles vous avez déjà acquis de la mémoire musculaire, comme

env | uniq | sort -r | grep PATH

ou

my-web-server 2>&1 | my-log-sorter

fonctionnera toujours bien.

Le didacticiel est assez long et semble couvrir une partie importante des fonctionnalités auxquelles on s'attendrait généralement lors d'une invite de cendres ou de bash:

  • Compile, évalue et exécute!
  • Historique des commandes et complétion des onglets
  • Aide & Aide Super avec ? & ??
  • Alias ​​et invites personnalisées
  • Exécute des commandes et/ou des scripts *.xsh Qui peuvent également être importés
  • Variables d'environnement, y compris la recherche avec ${}
  • Redirection entrée/sortie et combinaison
  • Travaux en arrière-plan et contrôle des travaux
  • Imbrication de sous-processus, de tubes et de co-processus
  • Mode sous-processus lorsqu'une commande existe, mode Python sinon
  • Sous-processus capturé avec $(), sous-processus non capturé avec $[], Python Évaluation avec @()
  • Globbing de nom de fichier avec * Ou Expression régulière Globbing de nom de fichier avec Backticks
44
Kamilion
  • Si vous voulez utiliser Python en tant que shell, pourquoi ne pas jeter un œil à IPython ? Il est également bon d’apprendre le langage de manière interactive.
  • Si vous manipulez beaucoup de texte et utilisez Vim comme éditeur de texte, vous pouvez aussi écrire directement des plugins pour Vim en python. tapez simplement ": help python" dans Vim et suivez les instructions ou jetez un coup d'oeil à ceci présentation . Il est si facile et puissant d’écrire des fonctions que vous utiliserez directement dans votre éditeur!
31
Mapad

Au début, il y avait sh, sed et awk (et find, grep et ...). C'était bon. Mais awk peut être une petite bête étrange et difficile à retenir si vous ne l'utilisez pas souvent. Puis le grand chameau a créé Perl. Perl était le rêve d'un administrateur système. C'était comme les scripts de Shell sur les stéroïdes. Le traitement de texte, y compris les expressions régulières, faisait partie du langage. Ensuite, c'est devenu moche ... Les gens ont essayé de faire de grosses applications avec Perl. Maintenant, ne vous méprenez pas, Perl peut être une application, mais cela peut (peut!) Ressembler à un gâchis si vous ne faites pas vraiment attention. Ensuite, il y a toute cette affaire de données à plat. Il suffit de conduire un programmeur fou.

Entrez Python, Ruby et al. Ce sont vraiment de très bons langages à usage général. Ils prennent en charge le traitement de texte et le font bien (bien que peut-être moins étroitement lié au noyau de base du langage). Mais ils évoluent également très bien et ont toujours un code à la recherche de Nice à la fin de la journée. Ils ont également développé des communautés assez lourdes avec beaucoup de bibliothèques pour presque tout.

Maintenant, une grande partie de la négativité vis-à-vis de Perl est une question d’opinion, et certaines personnes peuvent écrire en Perl très propre, mais avec autant de gens qui se plaignent du fait qu’il est trop facile de créer du code obfusqué, vous savez qu’il existe un grain de vérité. La question devient alors vraiment, allez-vous jamais utiliser ce langage pour plus que de simples remplacements de script bash. Sinon, apprenez un peu plus Perl .. c'est absolument fantastique pour cela. Si, au contraire, vous voulez un langage qui grandira avec vous à mesure que vous voulez en faire plus, puis-je vous suggérer Python ou Ruby.

De toute façon, bonne chance!

16
MattG

Je suggère le livre en ligne génial plonger dans Python. C'est comme ça que j'ai appris la langue à l'origine.

En plus de vous enseigner la structure de base du langage et de nombreuses structures de données utiles, il contient un bon chapitre sur gestion des fichiers et les chapitres suivants sur expressions régulières et plus encore.

9
Dan Lenski

Ajout aux réponses précédentes: consultez le module pexpect pour gérer les commandes interactives (adduser, passwd, etc.)

7

Une des raisons pour laquelle j'aime Python) est qu'il est beaucoup mieux normalisé que les outils POSIX. Je dois vérifier deux ou trois fois que chaque bit est compatible avec d'autres systèmes d'exploitation. Un programme écrit sur un système Linux ne fonctionnera peut-être pas de la même manière sur un système BSD sous OSX. Avec Python, je dois juste vérifier que le système cible dispose d’une version suffisamment moderne de Python.

Mieux encore, un programme écrit en standard Python sera même exécuté sous Windows!

7
Hal Canary

Je vais donner ici mon avis basé sur l'expérience:

Pour Shell:

  • Shell peut très facilement générer du code en lecture seule. Écris-le et quand tu y reviendras, tu ne comprendras plus jamais ce que tu as fait. C'est très facile d'accomplir cela.
  • Shell peut faire BEAUCOUP de traitement de texte, de fractionnement, etc. en une seule ligne avec des tubes.
  • c’est le meilleur langage à utiliser pour intégrer l’appel de programmes dans différents langages de programmation.

Pour le python:

  • si vous voulez une portabilité vers les fenêtres incluses, utilisez python.
  • python peut être préférable lorsque vous devez manipuler un peu plus que du texte, tel que des ensembles de nombres. Pour cela, je recommande python.

Je choisis habituellement bash pour la plupart des choses, mais quand j'ai quelque chose qui doit traverser les frontières de la fenêtre, j'utilise simplement python.

6
Germán Diago

pythonpy est un outil qui permet d’accéder facilement à de nombreuses fonctionnalités de awk et sed, mais avec la syntaxe python:

$ echo me2 | py -x 're.sub("me", "you", x)'
you2
4
RussellStewart

En faisant des recherches sur ce sujet, j'ai trouvé ce code de preuve de concept (via un commentaire sur http://jlebar.com/2010/2/1/Replacing_Bash.html ) qui vous permet "d'écrire des pipelines de type Shell dans Python en utilisant une syntaxe abrégée et en exploitant les outils système existants là où ils ont un sens":

for line in sh("cat /tmp/junk2") | cut(d=',',f=1) | 'sort' | uniq:
    sys.stdout.write(line)
3
Nickolay

J'ai construit des scripts shell semi-longs (300-500 lignes) et Python qui propose des fonctionnalités similaires. Lorsque de nombreuses commandes externes sont en cours d'exécution, le shell est plus facile à utiliser. Perl est C'est également une bonne option lorsqu'il y a beaucoup de manipulation de texte.

3
Mike Davis

Votre meilleur pari est un outil spécifiquement adapté à votre problème. Si c'est le traitement de fichiers texte, Sed, Awk et Perl sont les principaux candidats. Python est un langage généraliste dynamique. Comme pour tout langage généraliste, la manipulation de fichiers est prise en charge, mais ce n'est pas son objectif principal. Je considérerais Python ou Ruby si j'avais besoin d'un langage dynamique en particulier.

En bref, découvrez Sed et Awk vraiment bien, ainsi que tous les autres avantages qui viennent avec votre parfum de * nix (Tous les éléments intégrés de Bash, grep, tr, etc.). traitement de fichier texte qui vous intéresse, vous utilisez déjà le bon matériel.

2
Eric Smith

Vous pouvez utiliser python au lieu de bash avec la bibliothèque ShellPy .

Voici un exemple qui télécharge l’avatar de Python utilisateur de Github:

import json
import os
import tempfile

# get the api answer with curl
answer = `curl https://api.github.com/users/python
# syntactic sugar for checking returncode of executed process for zero
if answer:
    answer_json = json.loads(answer.stdout)
    avatar_url = answer_json['avatar_url']

    destination = os.path.join(tempfile.gettempdir(), 'python.png')

    # execute curl once again, this time to get the image
    result = `curl {avatar_url} > {destination}
    if result:
        # if there were no problems show the file
        p`ls -l {destination}
    else:
        print('Failed to download avatar')

    print('Avatar downloaded')
else:
    print('Failed to access github api')

Comme vous pouvez le constater, toutes les expressions contenues dans le symbole accent grave (`) sont exécutées dans Shell. Et dans le code Python, vous pouvez capturer les résultats de cette exécution et y exécuter des actions. Par exemple:

log = `git log --pretty=oneline --grep='Create'

Cette ligne va d'abord exécuter git log --pretty=oneline --grep='Create' dans Shell, puis affectez le résultat à la variable de journal. Le résultat a les propriétés suivantes:

stdout tout le texte de stdout du processus exécuté

stderr tout le texte de stderr du processus exécuté

code de retour code de retour de l'exécution

Ceci est un aperçu général de la bibliothèque, une description plus détaillée avec des exemples peut être trouvée ici .

2
Alexander Ponomarev

J'ai publié un paquet sur PyPI: ez .
Utilisez pip install ez Pour l'installer.

Il a emballé des commandes communes dans Shell et ma bibliothèque utilise bien la même syntaxe que Shell. Par exemple, cp (source, destination) peut gérer à la fois un fichier et un dossier! (wrapper de shutil.copy shutil.copytree et il décide quand utiliser lequel). Mieux encore, il peut prendre en charge la vectorisation comme R!

Autre exemple: no os.walk, utilisez fls (chemin, regex) pour rechercher de manière récursive des fichiers et filtrer avec une expression régulière. Cette commande renvoie une liste de fichiers avec ou sans chemin complet.

Dernier exemple: vous pouvez les combiner pour écrire très simplement des scripts:
files = fls('.','py$'); cp(files, myDir)

Certainement vérifier! Cela m'a coûté des centaines d'heures pour l'écrire/l'améliorer!

1
Jerry T

Si votre manipulation de fichier texte est généralement ponctuelle, éventuellement effectuée sur l'invite du shell, vous n'obtiendrez rien de mieux avec python.

D'autre part, si vous devez généralement exécuter la même tâche (ou une tâche similaire) à maintes reprises et écrire vos scripts pour le faire, alors python est excellent - et vous pouvez créez facilement vos propres bibliothèques (vous pouvez aussi le faire avec des scripts Shell, mais c'est plus lourd).

Un exemple très simple pour avoir un sentiment.

import popen2
stdout_text, stdin_text=popen2.popen2("your-Shell-command-here")
for line in stdout_text:
  if line.startswith("#"):
    pass
  else
    jobID=int(line.split(",")[0].split()[1].lstrip("<").rstrip(">"))
    # do something with jobID

Vérifiez également sys et le module getopt, ils sont les premiers dont vous aurez besoin.

1
Davide