2008-12-14 4 views
15

Ich kenne python -c '<code>', aber ich frage mich, ob es eine eleganter Python entspricht perl -pi -e '<code>'. Ich benutze es immer noch ziemlich für Dinge wie Suchen und Ersetzen in einem ganzen Verzeichnis (perl -pi -e s/foo/bar/g * oder sogar find . | xargs perl -pi -e s/foo/bar/g für Unterverzeichnisse).Gibt es ein Python-Äquivalent zu "perl -pi -e"?

Ich fühle tatsächlich, dass das, was Perl Perl macht (freie Form Tim Toady-Ness) ist, was perl -pi -e Arbeit so gut macht, während mit Python müssten Sie etwas in Richtung des Importierens des RE-Moduls tun, ein re-Instanz und dann erfassen stdin, aber vielleicht gibt es eine Python-Verknüpfung, die all das tut und ich verpasste es (schmerzlich vermisst) ...

+2

Ehrlich gesagt klingt es nach etwas, was Guido nicht gutheißen würde. – Axeman

+0

Sicher meinst du finden. -type f | xargs perl ...? –

+0

Sie können stattdessen Ruby verwenden. In Ruby ist das Äquivalent von "perl -pi -e" "Ruby -pi -e". Klicken Sie auf [diesen Link] (http://stackoverflow.com/questions/1274605/ruby-search-file-text-for-a-pattern-and-replace-it-with-a-given-value#3502884) für mehr Information. – unforgettableid

Antwort

9

Die Befehlszeilenverwendung von 'python -h' deutet sicherlich stark darauf hin, dass es kein Äquivalent gibt. Perl verwendet häufig '$_' (Ihre Beispiele verwenden es implizit), und ich glaube nicht, dass Python ein ähnliches Konzept unterstützt, wodurch Python-Äquivalente der Perl-Einzeiler viel schwieriger werden.

24

Python ist für Muggel. Wenn Magie du willst, solltest du Perl benutzen!

10

Ein Äquivalent zu -pi ist nicht so schwer in Python zu schreiben.

  1. Schreiben Sie sich ein handliches Modul mit den Funktionen -p und -i, die Ihnen wirklich gefallen. Nennen wir es pypi.py.

  2. Verwenden python -c 'import pypi; pypi.subs("this","that")'

Sie können die Grund -p Schleife mit dem fileinput Modul implementieren.

Sie hätten eine Funktion, subs, die den essenziellen "-i" -Algorithmus implementiert, eine Datei zu öffnen, die Sicherungskopie zu speichern und in jeder Zeile den Ersatz zu machen.

Es gibt einige activestate Rezepte wie dieses. Hier sind einige:

Nicht eingebaut. Aber nicht schwer zu schreiben. Und einmal geschrieben, einfach anzupassen.

+3

Ich würde vorschlagen, dass das Modul pi.py heißt, im Verzeichnis site-packages gespeichert wird, mit einem 'if __name__ ==" __main __ ":' construct endet und dann mit 'python -mpi aufgerufen wird ... ' – tzot

6

Ich denke Perl ist besser geeignet für diese Art von On-The-Fly-Skripting. Wenn Sie schnelle On-the-Fly-Skriptingfunktionen benötigen, sollten Sie sich an die Befehlszeilentools perl, awk, sed und standard unix halten.

Aber wenn Sie in Python verwenden möchten, verwende ich optparse, um meine eigenen Befehlszeilenprogramme zu schreiben und zu empfehlen. optparse bietet einen sauberen und einfach zu verwendenden Befehlszeilenoptionsparser mit integrierter Hilfegenerierung.

Hier ist ein Beispiel:

def myfunc(filename, use_versbose): 
    # function code 

if __name__ == '__main__': 
    from optparse import OptionParser 

    parser = OptionParser() 
    parser.add_option("-f", "--file", dest="filename", 
         help="write report to FILE", metavar="FILE") 
    parser.add_option("-q", "--quiet", 
         action="store_false", dest="verbose", default=True, 
         help="don't print status messages to stdout") 

    (options, args) = parser.parse_args() 

    if options.filename: 
     myfunc(options.filename, options.verbose) 

    else: 
     print 'ERROR -- Necessary command line options not given!' 
     print parser.print_help() 

Parser.print_help() erzeugt die folgende Ausgabe und wird automatisch angezeigt, wenn -h oder --help in der Befehlszeile angegeben:

usage: <yourscript> [options] 

options: 
    -h, --help   show this help message and exit 
    -f FILE, --file=FILE write report to FILE 
    -q, --quiet   don't print status messages to stdout 
+3

Dies ist in keinster Weise ein Ersatz für einen Einzeiler, und daher ist das meiste davon keine Antwort auf die Frage –

+3

Ja, aber vielleicht ist die elegantere Lösung nicht gleichwertig zu 'Perl -pi-e' , aber schreiben Sie Ihre eigenen Kommandozeilen-Tools für häufig durchgeführte Aufgaben. "myscript.py -x this -y das" könnte sauberer sein als "python -c" importiere das; dostuff (this, das) '". Es hängt von Ihren individuellen Bedürfnissen und Vorlieben ab. – monkut

2

Das fileinput Modul die Fähigkeit zur in-Place-Bearbeitung hat. Sie können jedoch nicht auf die Backups verzichten. Hier ist, wie es zu benutzen für einen Einzeiler:

python -c 'import fileinput, sys; for line in fileinput.input(inplace=True): sys.stdout.write(line, "foo", "bar")' 

Ich persönlich in der Regel nur Perl verwenden, wenn ich so etwas wie dies tun müssen. Es ist eines der wenigen Male, dass ich Perl benutze.

9

Ich weiß, das ein paar Jahre zu spät, aber ich habe vor kurzem ein sehr schönes Werkzeug pyp, die genau funktioniert genannt gefunden, was Sie schon gefragt.

Ich denke, Ihr Befehl sollte:

pyp "p.replace('foo','bar')" 
+1

Schöner Fund! pyp ("The Pyed Piper, Piping Python Through Pipes"), von Sony Pictures Imageworks, ist sehr prägnant, flexibel, kann Statistiken, interne Pipelines, etc. Es wurde auf der PYCON 2012 "The Pyed Piper: Ein moderner Python Alternative zu awk, sed und anderen Unix Text Manipulation Utilities von Toby Rosen " – nealmcb

0

Die oben arbeiten kann für stdin, aber sieht nicht, wie es für eine Datei funktionieren würde.

Vielleicht so etwas wie:

-

import fileinput 
import sys 
for line in fileinput.input("./poop", inplace=True): 
    line = line.replace("foo", "bar") 
    sys.stdout.write(line) 

- wo "./poop" kann ersetzt werden, in dem Sie Ihre Datei und line.replace sollten Dinge wie line.replace unterstützen ("{}". format (variablehere), "newtext")

Verwandte Themen