Grep und Python

78

Ich brauche eine Möglichkeit, eine Datei mit grep über einen regulären Ausdruck in der Unix-Befehlszeile zu durchsuchen. Zum Beispiel, wenn ich in die Befehlszeile eingebe:

python pythonfile.py 'RE' 'file-to-be-searched'

Ich brauche den regulären Ausdruck 'RE', um in der Datei gesucht zu werden und die passenden Zeilen auszudrucken.

Hier ist der Code, den ich habe:

import re
import sys

search_term = sys.argv[1]
f = sys.argv[2]

for line in open(f, 'r'):
    if re.search(search_term, line):
        print line,
        if line == None:
            print 'no matches found'

Aber wenn ich ein Wort eingebe, das nicht vorhanden ist, wird no matches foundes nicht gedruckt

David
quelle
1
Wenn Sie wirklich reguläre Ausdrücke im Python-Stil in grep suchen, ist die Option --perl-regex für grep sehr nahe. Es bietet Ihnen Unterstützung für reguläre Ausdrücke im Perl-Stil. (Auch meine Lieblingsoption zu grep ist --color = always)
Ross Rogers

Antworten:

82

Die natürliche Frage ist, warum nicht einfach grep verwenden?! Aber vorausgesetzt du kannst nicht ...

import re
import sys

file = open(sys.argv[2], "r")

for line in file:
     if re.search(sys.argv[1], line):
         print line,

Dinge zu beachten:

  • searchanstatt matchirgendwo in der Zeichenfolge zu finden
  • Komma ( ,) nach dem printEntfernen des Wagenrücklaufs (Zeile hat einen)
  • argv Enthält den Namen der Python-Datei, daher müssen Variablen bei 1 beginnen

Dies behandelt nicht mehrere Argumente (wie es grep tut) oder erweitert Platzhalter (wie es die Unix-Shell tun würde). Wenn Sie diese Funktionalität wünschen, können Sie sie wie folgt erhalten:

import re
import sys
import glob

for arg in sys.argv[2:]:
    for file in glob.iglob(arg):
        for line in open(file, 'r'):
            if re.search(sys.argv[1], line):
                print line,
Nick Fortescue
quelle
7
Sie sollten Ihren regulären Ausdruck kompilieren, bevor Sie die Schleifen verwenden.
Ghostdog74
5
Dies hat zwei Abstimmungen und ich habe keine Ahnung warum. Wer downvoted hat, möchte einen Kommentar hinterlassen? Ich weiß, dass Sie Regex-Kompilierung usw. hinzufügen könnten, aber ich dachte, das würde die Klarheit der Antwort beeinträchtigen. Ich glaube nicht, dass irgendetwas falsch ist, und ich habe den Code ausgeführt, im Gegensatz zu einigen anderen Antworten
Nick Fortescue
Diese Antwort war perfekt für mich, danke. Nur eine weitere kurze Frage: Wie würde ich drucken, wenn keine Übereinstimmungen gefunden würden?
David
6
"Sie sollten Ihren regulären Ausdruck kompilieren, bevor Sie die Schleifen verwenden.", Nein, Python kompiliert und speichert ihn selbstständig. Dies ist ein weit verbreiteter Mythos. Aus Gründen der Lesbarkeit ist dies eine gute Sache.
Bartekbrak
4
Die vernünftige Antwort auf die natürliche Frage lautet: "Weil der Code Teil eines viel größeren Python-Skripts ist und wer in einem solchen Fall nach Grep rufen möchte?" Kurz gesagt, ich bin froh, dass diese Frage hier ist, weil ich ein Bash-Skript durch ein Python-Skript ersetze, das das System hoffentlich einfacher macht.
Mike S
13

Prägnant und speichereffizient:

#!/usr/bin/env python
# file: grep.py
import re, sys

map(sys.stdout.write,(l for l in sys.stdin if re.search(sys.argv[1],l)))

Es funktioniert wie egrep (ohne zu viel Fehlerbehandlung), zB:

cat input-file | grep.py "RE"

Und hier ist der Einzeiler:

cat input-file | python -c "import re,sys;map(sys.stdout.write,(l for l in sys.stdin if re.search(sys.argv[1],l)))" "RE"
Giancarlo Sportelli
quelle
7

Adaptiert von einem Grep in Python .

Akzeptiert eine Liste von Dateinamen über [2:], führt keine Ausnahmebehandlung durch:

#!/usr/bin/env python
import re, sys, os

for f in filter(os.path.isfile, sys.argv[2:]):
    for line in open(f).readlines():
        if re.match(sys.argv[1], line):
            print line

sys.argv[1]resp sys.argv[2:]funktioniert, wenn Sie es als eigenständige ausführbare Datei ausführen, was bedeutet

chmod +x

zuerst

miku
quelle
Was ist der Unterschied zwischen re.match und re.search?
OscarRyz
2
@OscarRyz siehe Nick Fortescues Top-Antwort : " searchAnstatt matchirgendwo in der Zeichenfolge zu finden"
icc97
4
  1. Verwenden Sie sys.argvdiese Option, um die Befehlszeilenparameter abzurufen
  2. Verwenden Sie open(), read()um die Datei zu bearbeiten
  3. Verwenden Sie das Python re-Modul , um Linien abzugleichen
jldupont
quelle
3

Sie könnten an Pyp interessiert sein . Unter Berufung auf meine andere Antwort :

"The Pyed Piper" oder pyp ist ein Linux-Befehlszeilentext-Manipulationstool, 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.

Piotr Dobrogost
quelle
1

Sie können Python-Textops3 verwenden:

from textops import *

print('\n'.join(cat(f) | grep(search_term)))

Mit Python-Textops3 können Sie Unix-ähnliche Befehle mit Pipes verwenden

Eric
quelle
0

Das eigentliche Problem ist, dass die variable Zeile immer einen Wert hat. Der Test für "Keine Übereinstimmungen gefunden" besteht darin, ob eine Übereinstimmung vorliegt. Daher sollte der Code "if line == None:" durch "else:" ersetzt werden.

Richard
quelle