Wie implementiere ich allgemeine Bash-Redewendungen in Python? [geschlossen]


242

Momentan manipuliere ich meine Textdateien durch ein paar schlecht erinnerte AWK, Sed, Bash und ein kleines Stück Perl.

Ich habe einige Stellen erwähnt, an denen Python für solche Dinge gut ist. Wie kann ich Python verwenden, um Shell-Scripting, AWK, Sed und Freunde zu ersetzen?


3
Pythonpy ist ein guter Konkurrent für awk und sed mit Python-Syntax: github.com/Russell91/pythonpy
RussellStewart

4
Sie können Shellpy verwenden, das mit dem Gedanken entwickelt wurde, bash / sh durch python zu ersetzen. github.com/lamerman/shellpy
Alexander Ponomarev

Dies ist meine Frage, ich verstehe nicht, warum es meinungsbasiert ist. In der oberen Antwort werden die wichtigsten Aufgaben einer Shell aufgelistet und erläutert, wie sie in Python ausgeführt werden. Das beantwortet meiner Meinung nach die Frage ohne Meinung.
Chris Jefferson

Diese Frage und ihr Abschluss werden hier
Erik A

Antworten:


144

Jede Shell verfügt über mehrere Funktionen.

  • Die Essential Linux / Unix-Befehle. All dies ist über die Unterprozessbibliothek verfügbar . Dies ist nicht immer die beste erste Wahl für alle externen Befehle. Schauen Sie sich auch shutil für einige Befehle an, die separate Linux-Befehle sind, aber Sie könnten sie wahrscheinlich direkt in Ihre Python-Skripte implementieren. Eine weitere große Menge von Linux-Befehlen befindet sich in der Betriebssystembibliothek . Sie können dies einfacher in Python tun.

    Und - Bonus! -- schneller. Jeder separate Linux-Befehl in der Shell (mit wenigen Ausnahmen) gibt einen Unterprozess aus. Mit Python shutilund osModulen verzweigen Sie keinen Unterprozess.

  • Die Shell-Umgebung bietet Funktionen. Dies schließt Dinge ein, die die Umgebung eines Befehls festlegen (aktuelle Verzeichnis- und Umgebungsvariablen und was nicht). Sie können dies einfach direkt von Python aus verwalten.

  • Die Shell-Programmierfunktionen. Dies ist die gesamte Überprüfung des Prozessstatuscodes, die verschiedenen Logikbefehle (wenn, während, für usw.), der Testbefehl und alle seine Verwandten. Das Funktionsdefinitionsmaterial. Dies ist alles viel, viel einfacher in Python. Dies ist einer der großen Siege, wenn es darum geht, Bash loszuwerden und es in Python zu tun.

  • Interaktionsfunktionen. Dies beinhaltet den Befehlsverlauf und was nicht. Sie benötigen dies nicht zum Schreiben von Shell-Skripten. Dies ist nur für die menschliche Interaktion und nicht für das Schreiben von Skripten.

  • Die Funktionen zur Verwaltung von Shell-Dateien. Dies umfasst Umleitungen und Pipelines. Das ist schwieriger. Vieles davon kann mit Unterprozessen gemacht werden. Aber einige Dinge, die in der Shell einfach sind, sind in Python unangenehm. Speziell Sachen wie (a | b; c ) | something >result. Dies führt zwei Prozesse parallel aus (mit Ausgabe aals Eingabe für b), gefolgt von einem dritten Prozess. Die Ausgabe dieser Sequenz wird parallel ausgeführt somethingund die Ausgabe wird in einer Datei mit dem Namen gesammelt result. Das ist einfach komplex, um es in einer anderen Sprache auszudrücken.

Bestimmte Programme (awk, sed, grep usw.) können häufig als Python-Module umgeschrieben werden. Geh nicht über Bord. Ersetzen Sie das, was Sie brauchen, und entwickeln Sie Ihr "grep" -Modul weiter. Beginnen Sie nicht damit, ein Python-Modul zu schreiben, das "grep" ersetzt.

Das Beste ist, dass Sie dies schrittweise tun können.

  1. Ersetzen Sie AWK und PERL durch Python. Lass alles andere in Ruhe.
  2. Schauen Sie sich an, wie Sie GREP durch Python ersetzen. Dies kann etwas komplexer sein, aber Ihre GREP-Version kann auf Ihre Verarbeitungsanforderungen zugeschnitten werden.
  3. Sehen Sie sich an, wie Sie FIND durch Python-Schleifen ersetzen, die verwendet werden os.walk. Dies ist ein großer Gewinn, da Sie nicht so viele Prozesse erzeugen.
  4. Sehen Sie sich an, wie Sie die allgemeine Shell-Logik (Schleifen, Entscheidungen usw.) durch Python-Skripte ersetzen.

6
schrieb: "Interaktionsfunktionen. Dies beinhaltet den Befehlsverlauf und was nicht. Sie brauchen das nicht." Ich fürchte, niemand könnte sagen, was eine Person wirklich braucht oder nicht. Vielleicht tut er es. Außerdem sind diese Funktionen in einer interaktiven Shell sehr sinnvoll, wobei der Unterschied zwischen Idle und IPython als Beispiel dient.
Heltonbiker

47
Ich wünschte aufrichtig, die Leute würden das Shell-Scripting ganz aufgeben. Ich verstehe, dass Hacking in der * nix-Welt praktisch eine Religion ist, aber ich habe es wirklich satt, zu versuchen, alle im Betriebssystem implantierten hackischen Problemumgehungen zu interpretieren. Die Neuheit der Mikrotools (awk, sed, top, base usw.) ließ nach, als jeder beschloss, seine eigene Version zu rollen. Ich erschrecke, wenn ich mir vorstelle, wie viel Arbeitsstunden für beschissene kleine Werkzeuge verschwendet werden, die leicht durch ein paar gut gestaltete Python-Module ersetzt werden könnten. :: seufz ::
Evan Plaice

40
Ich bin mit @EvanPlaice nicht einverstanden, da die Python-Version mehrerer findSkripte, die ich habe, hässlich und lang ist und im Vergleich nicht gewartet werden kann. Viele Dinge sollten Shell-Skripte sein, viele andere nicht . Nicht alles muss nur Python oder BASH (oder irgendetwas anderes) sein.
Mikebabcock

8
@mikebabcock Idealerweise gibt es eine vollständige Bibliothek, die alle Mikro-Tools implementiert, die vom Basis-* nix-Stack zur Verfügung gestellt werden. Funktionen wie find () und last () wären enthalten, und anstelle von Rohren würde eine Kombination aus Currying und Lazy-Loading das Zusammenkleben übernehmen. Wäre es nicht schön, eine POSIX-Skriptumgebung zu haben, die in allen Distributionen standardmäßig funktioniert? Es gibt noch nichts
Evan Plaice

2
Der Punkt über Shell-Pipelines (wie (a | b; c ) | something >result) wird etwas gemildert, da es trivial einfach ist, Shell-Pipelines an subprocessMethoden zu übergeben, dieshell=True
iruvar

103

Ja natürlich :)

Schauen Sie sich diese Bibliotheken an, die Ihnen helfen, nie wieder Shell-Skripte zu schreiben (Plumbums Motto).

Wenn Sie awk, sed und grep durch etwas Python-basiertes ersetzen möchten, empfehle ich pyp -

"The Pyed Piper" oder pyp ist ein Linux-Befehlszeilentext-Manipulationswerkzeug, das awk oder sed ähnelt, jedoch Standardmethoden für Python-Strings und -Listen sowie benutzerdefinierte Funktionen verwendet, um schnelle Ergebnisse in einer intensiven Produktionsumgebung zu erzielen.


Schauen Sie sich auch Envoy an, eine Alternative zu sh github.com/kennethreitz/envoy
AllanLRH

57

Ich habe gerade herausgefunden, wie man die besten Teile von Bash und Ipython kombiniert. Bisher scheint mir dies angenehmer zu sein als die Verwendung von Unterprozessen und so weiter. Sie können problemlos große Teile vorhandener Bash-Skripte kopieren und z. B. die Fehlerbehandlung auf Python-Weise hinzufügen :) Und hier ist mein Ergebnis:

#!/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 ;)

Siehe IPython-Dokumente zu System-Shell-Befehlen und deren Verwendung als System-Shell .


11
Upvoted, weil aus irgendeinem bizarren Grund niemand sonst! -Befehle in IPython erwähnt hat, die absolut wichtig sind; zumal Sie ihre Ausgabe auch einer Variablen (Liste der Zeilen) zuweisen können, wie infilelines = ! cat myfile
kampu

Und Sie können Python-Variablen wie $varin einem Shell-Befehl verwenden? Beeindruckend. Dies sollte die akzeptierte Antwort sein.
Chiel ten Brinke

Und Sie können es auch aus den Jupyter-Notizbüchern heraus verwenden
Yuval Atzmon

44

Ab 2015 und der Veröffentlichung von Python 3.4 ist jetzt eine einigermaßen vollständige benutzerinteraktive Shell verfügbar: http://xon.sh/ oder https://github.com/scopatz/xonsh

Das Demonstrationsvideo zeigt keine verwendeten Pipes, sie werden jedoch im Standard-Shell-Modus unterstützt.

Xonsh ('Muschel') ist sehr bemüht, Bash zu emulieren, also Dinge, für die Sie bereits Muskelgedächtnis gewonnen haben, wie z

env | uniq | sort -r | grep PATH

oder

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

wird immer noch gut funktionieren.

Das Tutorial ist ziemlich langwierig und scheint einen erheblichen Teil der Funktionalität abzudecken, die man normalerweise bei einer Asche- oder Bash-Eingabeaufforderung erwarten würde:

  • Kompiliert, bewertet und führt aus!
  • Befehlsverlauf und Tab-Vervollständigung
  • Hilfe & Superhilfe mit ?&??
  • Aliase und benutzerdefinierte Eingabeaufforderungen
  • Führt Befehle und / oder aus *.xsh Skripte aus, die auch importiert werden können
  • Umgebungsvariablen einschließlich Nachschlagen mit ${}
  • Eingabe / Ausgabe-Umleitung und Kombination
  • Hintergrundjobs & Jobkontrolle
  • Verschachteln von Unterprozessen, Pipes und Coprozessen
  • Unterprozessmodus, wenn ein Befehl vorhanden ist, sonst Python-Modus
  • $()Erfasster Unterprozess mit , Nicht erfasster Unterprozess mit $[], Python-Auswertung mit@()
  • Dateiname Globbing mit *oder regulärer Ausdruck Dateiname Globbing mit Backticks

Aber warum scheinen all diese Antworten das Rad für Leute neu zu erfinden, die Bash nicht kennen ? Ich habe mich mit Bash mäßig wohlgefühlt und jede dieser Antworten scheint mehr Arbeit für wenig Nutzen zu sein. Diese Antworten richten sich alle an Python-Leute, die Angst vor Bash haben (oder keine Zeit damit verbringen wollen), stimmt's?
Buttle Butkus

Es scheint, dass es einige Nachteile hat, wie die Anforderung, die .xshErweiterung für Dateien mit dem xonsh-Code zu verwenden: github.com/xonsh/xonsh/issues/2478 . Andernfalls müssen Sie es verwenden evalx, um es direkt aus den .pyDateien aufzurufen .
Andry

31
  • Wenn Sie Python als Shell verwenden möchten, schauen Sie sich doch IPython an . Es ist auch gut, die Sprache interaktiv zu lernen.
  • Wenn Sie viel Text bearbeiten und Vim als Texteditor verwenden, können Sie auch direkt Plugins für Vim in Python schreiben. Geben Sie einfach ": help python" in Vim ein und folgen Sie den Anweisungen oder sehen Sie sich diese Präsentation an . Es ist so einfach und leistungsstark, Funktionen zu schreiben, die Sie direkt in Ihrem Editor verwenden werden!

8
Es gibt ein Ipython-Profil namens 'sh', das den Interpreter einer Shell sehr ähnlich macht .
Autoplektische

3
Das ipython 'sh'-Profil wurde seit einiger Zeit entfernt.
GDW2

>>> result =! dmesg | grep -i 'usb' #the! Betreiber macht alles
Permafacture

16

Am Anfang gab es sh, sed und awk (und find und grep und ...). Es war gut. Aber awk kann ein seltsames kleines Tier sein und schwer zu merken sein, wenn Sie es nicht oft benutzen. Dann erschuf das große Kamel Perl. Perl war der Traum eines Systemadministrators. Es war wie Shell-Scripting auf Steroiden. Textverarbeitung, einschließlich regulärer Ausdrücke, war nur ein Teil der Sprache. Dann wurde es hässlich ... Die Leute versuchten, mit Perl große Anwendungen zu machen. Versteh mich nicht falsch, Perl kann eine Anwendung sein, aber es kann (kann!) Wie ein Chaos aussehen, wenn du nicht wirklich vorsichtig bist. Dann gibt es all dieses Flat-Data-Geschäft. Es ist genug, um einen Programmierer verrückt zu machen.

Geben Sie Python, Ruby, et al. Dies sind wirklich sehr gute Allzwecksprachen. Sie unterstützen die Textverarbeitung und machen es gut (obwohl sie vielleicht nicht so eng mit dem Grundkern der Sprache verbunden sind). Aber sie lassen sich auch sehr gut skalieren und haben am Ende des Tages immer noch gut aussehenden Code. Sie haben auch ziemlich starke Communities mit vielen Bibliotheken für fast alles entwickelt.

Nun, ein Großteil der Negativität gegenüber Perl ist Ansichtssache, und sicherlich können einige Leute sehr sauberes Perl schreiben, aber da sich so viele Leute darüber beschweren, dass es zu einfach ist, verschleierten Code zu erstellen, wissen Sie, dass ein Körnchen Wahrheit da ist. Dann stellt sich wirklich die Frage, ob Sie diese Sprache jemals für mehr als nur einfache Ersetzungen von Bash-Skripten verwenden werden. Wenn nicht, lerne etwas mehr Perl. Es ist absolut fantastisch dafür. Wenn Sie andererseits eine Sprache möchten, die mit Ihnen wächst, wenn Sie mehr tun möchten, kann ich Python oder Ruby vorschlagen.

Wie auch immer, viel Glück!




7

Ein Grund, warum ich Python liebe, ist, dass es viel besser standardisiert ist als die POSIX-Tools. Ich muss doppelt und dreifach überprüfen, ob jedes Bit mit anderen Betriebssystemen kompatibel ist. Ein auf einem Linux-System geschriebenes Programm funktioniert auf einem BSD-System von OSX möglicherweise nicht gleich. Bei Python muss ich nur überprüfen, ob das Zielsystem über eine ausreichend moderne Version von Python verfügt.

Noch besser ist, dass ein in Standard-Python geschriebenes Programm sogar unter Windows ausgeführt werden kann!


1
"Ein in Standard-Python geschriebenes Programm läuft sogar unter Windows": kein Scherz?
Jean-François Fabre

6

Ich werde hier meine erfahrungsbasierte Meinung abgeben:

Für Shell:

  • Shell kann sehr leicht schreibgeschützten Code erzeugen. Schreiben Sie es und wenn Sie darauf zurückkommen, werden Sie nie wieder herausfinden, was Sie getan haben. Dies ist sehr einfach zu erreichen.
  • Shell kann eine Menge Textverarbeitung, Aufteilung usw. in einer Zeile mit Pipes ausführen.
  • Es ist die beste Klebesprache, wenn es darum geht, den Aufruf von Programmen in verschiedene Programmiersprachen zu integrieren.

Für Python:

  • Wenn Sie die Portabilität auf Windows wünschen, verwenden Sie Python.
  • Python kann besser sein, wenn Sie nur mehr als nur Text bearbeiten müssen, z. B. Sammlungen von Zahlen. Dafür empfehle ich Python.

Normalerweise wähle ich Bash für die meisten Dinge, aber wenn ich etwas habe, das Fenstergrenzen überschreiten muss, verwende ich einfach Python.


4

pythonpy ist ein Tool, das einfachen Zugriff auf viele der Funktionen von awk und sed bietet, jedoch die Python-Syntax verwendet:

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

3

Ich habe halblange Shell-Skripte (300-500 Zeilen) und Python-Code erstellt, der ähnliche Funktionen bietet. Wenn viele externe Befehle ausgeführt werden, ist die Shell meiner Meinung nach einfacher zu verwenden. Perl ist auch eine gute Option, wenn viel Text bearbeitet wird.



2

Ihre beste Wahl ist ein Tool, das speziell auf Ihr Problem zugeschnitten ist. Wenn es darum geht, Textdateien zu verarbeiten, sind Sed, Awk und Perl die Top-Konkurrenten. Python ist eine dynamische Allzwecksprache . Wie bei jeder Allzwecksprache wird die Dateimanipulation unterstützt, aber das ist nicht der Hauptzweck. Ich würde Python oder Ruby in Betracht ziehen, wenn ich insbesondere eine dynamische Sprache benötigen würde.

Kurz gesagt, lernen Sie Sed und Awk sehr gut und alle anderen Extras, die mit Ihrem Geschmack von * nix einhergehen (Alle eingebauten Bash-Funktionen, grep, tr usw.). Wenn Sie an der Verarbeitung von Textdateien interessiert sind, verwenden Sie bereits das richtige Material.


2

Sie können Python anstelle von Bash mit dem ShellPy verwenden Bibliothek verwenden.

Hier ist ein Beispiel, das den Avatar eines Python-Benutzers von Github herunterlädt:

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')

Wie Sie sehen können, werden alle Ausdrücke innerhalb des Symbols für schwerwiegende Akzente (`) in einer Shell ausgeführt. Im Python-Code können Sie die Ergebnisse dieser Ausführung erfassen und Aktionen ausführen. Beispielsweise:

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

Diese Zeile wird zuerst git log --pretty=oneline --grep='Create'in der Shell ausgeführt und weist das Ergebnis dann der Protokollvariablen zu. Das Ergebnis hat folgende Eigenschaften:

stdout den gesamten Text von stdout des ausgeführten Prozesses

stderr den gesamten Text von stderr des ausgeführten Prozesses

Rückkehrcode Rückkehrcode der Ausführung

Dies ist eine allgemeine Übersicht über die Bibliothek. Eine ausführlichere Beschreibung mit Beispielen finden Sie hier .


1

Wenn Ihre Textdatei-Manipulation normalerweise einmalig ist und möglicherweise an der Shell-Eingabeaufforderung ausgeführt wird, erhalten Sie mit Python nichts Besseres.

Auf der anderen Seite ist Python großartig, wenn Sie normalerweise immer wieder dieselbe (oder eine ähnliche) Aufgabe ausführen müssen und Ihre Skripte dafür schreiben müssen - und Sie können ganz einfach Ihre eigenen Bibliotheken erstellen (das können Sie tun) das auch mit Shell-Skripten, aber es ist umständlicher).

Ein sehr einfaches Beispiel, um ein Gefühl zu bekommen.

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

Überprüfen Sie auch sys und getopt module, sie sind die ersten, die Sie benötigen.


1

Ich habe ein Paket auf PyPI veröffentlicht: ez .
Verwenden Sie pip install ez, um es zu installieren.

Es hat allgemeine Befehle in die Shell gepackt und meine Bibliothek verwendet im Grunde die gleiche Syntax wie die Shell. zB kann cp (Quelle, Ziel) sowohl Datei als auch Ordner verarbeiten! (Wrapper von shutil.copy shutil.copytree und es entscheidet, wann welche verwendet werden soll). Noch schöner ist, dass es Vektorisierung wie R unterstützen kann!

Ein weiteres Beispiel: no os.walk, verwenden Sie fls (Pfad, Regex), um rekursiv Dateien zu finden und mit regulären Ausdrücken zu filtern, und es wird eine Liste von Dateien mit oder ohne vollständigen Pfad zurückgegeben

Letztes Beispiel: Sie können sie kombinieren, um sehr einfache Skripte zu schreiben:
files = fls('.','py$'); cp(files, myDir)

Probieren Sie es auf jeden Fall aus! Es hat mich Hunderte von Stunden gekostet, es zu schreiben / zu verbessern!


1
Sieht interessant aus, aber ich kann die unformatierten Dokumente unter pypi.python.org/pypi/ez nicht durchbrechen , sorry ...
Greg Dubicki
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.