16 Stimmen

Python-Äquivalent zu perl -pe?

Ich muss einige Zahlen aus einigen Textdateien heraussuchen. Ich kann die benötigten Zeilen mit grep heraussuchen, aber ich wusste nicht, wie ich die Zahlen aus den Zeilen extrahieren kann. Ein Kollege hat mir gezeigt, wie ich das mit Bash und Perl machen kann:

cat results.txt | perl -pe 's/.+(\d\.\d+)\.\n/\1 /'

Allerdings programmiere ich normalerweise in Python, nicht in Perl. Meine Frage ist also, ob ich Python auf dieselbe Weise hätte verwenden können. D.h., hätte ich etwas von Bash nach Python pipen können und dann das Ergebnis direkt nach stdout bekommen? ... wenn das Sinn macht. Oder ist Perl in diesem Fall einfach praktischer?

1 Stimmen

Sie könnten es sich noch einmal überlegen und das gesamte Parsing in Python durchführen. Es wäre wahnsinnig einfach, die Greping von Python zu tun. Wenn Sie Probleme haben, stellen Sie einfach eine weitere Frage mit dem Wortlaut "Wie kann ich diese Zeilen in Python analysieren", und 5 Minuten später haben Sie den Code

0 Stimmen

@TJD: Stimmt. Ich werde das in Betracht ziehen.

0 Stimmen

Nachdem ich einige Antworten und Methoden geprüft habe, frage ich: Würde es funktionieren, wenn Sie nur grep -o die nur den übereinstimmenden Teil der Zeile ausgibt?

12voto

Amber Punkte 473552

Ja, Sie können Python von der Kommandozeile aus verwenden. python -c <stuff> wird laufen <stuff> als Python-Code. Beispiel:

python -c "import sys; print sys.path"

Es gibt keine direkte Entsprechung zum -p Option für Perl (die automatische zeilenweise Verarbeitung von Ein- und Ausgaben), aber das liegt vor allem daran, dass Python nicht das gleiche Konzept von $_ und so weiter, wie es Perl tut - in Python werden alle Ein- und Ausgaben manuell vorgenommen (über raw_input() / input() et print / print() ).


Für Ihr spezielles Beispiel:

cat results.txt | python -c "import re, sys; print ''.join(re.sub(r'.+(\d\.\d+)\.\n', r'\1 ', line) for line in sys.stdin)"

(Offensichtlich etwas unhandlicher. Es ist wahrscheinlich besser, das Skript dafür in Python zu schreiben).

0 Stimmen

Seltsamerweise scheint die Version von Python, die ich verwende (2.7.1), Inline nicht zu mögen for Schleifen nach Semikolons - einfache Befehle funktionieren, aber komplexere Strukturen werfen ein SyntaxError .

1 Stimmen

@duskwuff - das ist zu erwarten. Semikolons haben keine Möglichkeit, Blöcke zu spezifizieren. Sie können stattdessen einen Comprehension/Generator-Ausdruck verwenden.

2voto

0xd Punkte 1891

Sie können verwenden:

$ python -c '<your code here>'

0 Stimmen

Vielen Dank für die rasche Antwort (an Sie und @Amber)! Das ist fast das, wonach ich gesucht habe, aber nicht ganz. Das ist analog zu perl -e, aber es gibt die Ausgabe nicht auf stdout aus. Also python -c 2+2 gibt nichts heraus. (Sie können verwenden python -c 'a=2+2; print a' natürlich, aber Sie verstehen, worauf ich hinaus will?)

0 Stimmen

@Nagel : alle Antworten beziehen sich auf eine Kommandozeilenmethode, aber verwenden Sie ein Skript? (zum Lesen einer Reihe von Dateien würde ich auf jeden Fall ein Skript verwenden)

2voto

Theoretisch ist das möglich, aber Python hat nicht annähernd so viel Regex-Magie wie Perl, so dass der resultierende Befehl viel unhandlicher sein wird, zumal man reguläre Ausdrücke nicht verwenden kann, ohne re (und Sie werden wahrscheinlich brauchen sys für sys.stdin auch).

Die Python-Entsprechung des Perl-Einzeilers Ihres Kollegen ist ungefähr:

import sys, re
for line in sys.stdin:
    print re.sub(r'.+(\d\.\d+)\.\n', r'\1 ', line)

0 Stimmen

Der Import von Standardmodulen sollte nicht als "unsauberer" oder anderweitig weniger robuster Code betrachtet werden, zumindest nicht in Python.

0 Stimmen

Danke! Das habe ich mir schon gedacht. Ich denke, ich werde einige grundlegende Perl für diese Art von Aufgabe dann lernen :)

0 Stimmen

@heltonbiker hat natürlich Recht, aber der resultierende Python-Code ist länger und scheint etwas unhandlich für die Verwendung als Kommandozeilen-Tool.

1voto

heltonbiker Punkte 24989

Sie haben ein Problem, das auf verschiedene Weise gelöst werden kann.

Ich denke, Sie sollten erwägen, reguläre Ausdrücke (was Perl in Ihrem Beispiel tut) direkt von Python aus zu verwenden. Reguläre Ausdrücke sind in der re Modul. Ein Beispiel wäre:

import re
filecontent = open('somefile.txt').read()
print re.findall('.+(\d\.\d+)\.$', filecontent)

(Ich würde die Verwendung von $ anstelle von \n ' für die Zeilenenden, da die Zeilenenden in den verschiedenen Betriebssystemen und Dateikodierungen unterschiedlich sind)

Wenn Sie Bash-Befehle aus Python heraus aufrufen wollen, können Sie dies tun:

import os
os.system(mycommand)

Dabei ist command der Bash-Befehl. Ich verwende ihn ständig, weil einige Operationen in der Bash besser durchzuführen sind als in Python.

Wenn Sie schließlich die Zahlen mit grep extrahieren wollen, verwenden Sie die -o Option, die nur den übereinstimmenden Teil ausgibt.

1voto

Perl (oder sed) ist bequemer. Es ist jedoch möglich, wenn auch hässlich:

python -c 'import sys, re; print "\n".join(re.sub(".+(\d\.\d+)\.\n","\1 ", l) for l in sys.stdin)'

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X