Shell-Skript:

logcat | grep -E "one|two|three"

Python-Code:

key_words = [ "one", "two", "three"]
log_lines = os.popen("logcat");

for log_line in log_lines:
   for keyword in key_words:
        if keyword in log_line:
             print log_line

Gibt es Optimierungen für den obigen Python-Code?

0
Lava Sangeetham 18 Jän. 2019 im 07:21

4 Antworten

Beste Antwort

Führen Sie die folgenden Schritte aus, um das genaue Muster in Ihrem Befehl grep zu emulieren

import re

pattern = re.compile('|'.join(key_words))

for log_line in log_lines:
    if pattern.search(log_line):
        print log_line

Wenn Sie Sonderzeichen zulassen möchten, müssen Sie ihnen entkommen:

pattern = re.compile('|'.join(re.escape(word) for word in key_words))

Wie Sie sich vorstellen können, ist die Verwendung von Regex in diesem Fall etwas übertrieben. Stattdessen können Sie eine direkte Suche durchführen. Sie können any verwenden, um bei der Suche zu helfen, da es kurzgeschlossen wird.

for log_line in log_lines:
    if any(word in log_line for word in key_words):
        print log_line

Dies führt eine lineare Suche der gesamten Zeile für jedes Schlüsselwort durch. Sie können dies etwas effizienter gestalten, wenn die Schlüsselwörter tatsächliche Wörter sein sollen, insbesondere da Sie bereits einen Satz für die Schlüsselwörter haben:

for log_line in log_lines:
    if keywords.intersection(set(log_line.split()):
        print log_line
2
Mad Physicist 18 Jän. 2019 im 05:11

Ihre vorgeschlagene Lösung druckt Zeilen mit mehreren Schlüsselwörtern so oft wie die Anzahl der Schlüsselwörter, die Sie möglicherweise vermeiden möchten. Wenn ein Schlüsselwort als Teil eines anderen Wortes angezeigt wird, wird es auch angezeigt (obwohl dies dem grep-Verhalten entspricht).

Einige Lösungen:

import os

key_words = {"one", "two", "three"}
log_lines = ['This has a one and a two', 'Some ones', 'This one has neither, oh it does', 'This does not', 'A three']

# fixing the repetition    
for log_line in log_lines:
   for keyword in key_words:
        if keyword in log_line:
             print(log_line)
             break

# fixing the repetition and partial matches
for log_line in log_lines:
    for word in log_line.split():
        if word in key_words:
            print(log_line)
            break

# single line solution
print([log_line for log_line in log_lines if key_words & set(log_line.split()) != set()])

# single line solution with partial matches
print([log_line for log_line in log_lines if any(key_word in log_line for key_word in key_words)])
0
Grismar 18 Jän. 2019 im 04:37

Eine erste Optimierung wäre, tatsächlich break zu verwenden, sobald Sie eine Übereinstimmung gefunden haben:

key_words = [ "one", "two", "three"]
log_lines = os.popen("logcat");

for log_line in log_lines:
    for keyword in key_words:
        if keyword in log_line:
            print log_line
            break    # stop looking for keywords if you already found one

Eine besser lesbare Lösung besteht darin, diese Schlüsselwortschleifenprüfung durch einen regulären Ausdruck zu ersetzen. Wenn es eine Übereinstimmung gibt, drucken Sie die Zeile aus:

import re
key_words = [ "one", "two", "three"]
regex = re.compile('|'.join(key_words))    # one|two|three

log_lines = os.popen("logcat");
for log_line in log_lines:
    if regex.match(log_line):    # returns None if no match, an object if there is a match
        print log_line

Vom Standpunkt der Leistung aus nicht sicher, welche schneller wäre, aber eine ist besser lesbar. Es gibt jedoch einige Einschränkungen bei den Ergebnissen.

0
sal 18 Jän. 2019 im 05:15

Hallo, Sie können den regulären Ausdruck verwenden und dieses Szenario ausprobieren. Sie können den regulären Ausdruck auch gemäß Ihren Anforderungen ändern. Überprüfen Sie das folgende Beispiel:

import re

key_words = [ "one", "two", "three"]
regex  = "|".join(key_words)
log_lines = open("logcat", 'r')
lines = log_lines.readlines()
print filter(lambda x : re.search(regex,x), lines)

log_lines.close()
0
Amit Nanaware 18 Jän. 2019 im 04:53