python grep несколько слов в logcat - PullRequest
0 голосов
/ 18 января 2019

Сценарий оболочки:

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

Код Python:

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

Есть ли какие-либо оптимизации для вышеприведенного кода Python?

Ответы [ 4 ]

0 голосов
/ 18 января 2019

Одной из первых оптимизаций будет фактически break, как только вы найдете одно совпадение:

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

Более удобное решение - заменить проверку цикла ключевого слова на регулярное выражение. Если есть совпадение, выведите строку:

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

С точки зрения производительности, не уверен, что будет быстрее, но один будет более читабельным. Однако в результатах есть некоторые оговорки.

0 голосов
/ 18 января 2019

Привет, вы можете использовать регулярное выражение и попробовать этот сценарий. Вы также можете изменить регулярное выражение в соответствии с приведенными ниже примерами проверки:

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 голосов
/ 18 января 2019

Чтобы подражать точному шаблону в вашей команде grep, выполните

import re

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

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

Если вы хотите разрешить спецсимволы, вам придется их избегать:

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

Как вы можете себе представить, использование регулярных выражений в этом случае немного излишне. Вместо этого вы можете сделать прямой поиск. Вы можете использовать any, чтобы помочь с поиском, так как он закорачивает.

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

Выполняет линейный поиск по всей строке для каждого ключевого слова. Вы можете сделать это немного более эффективным, если ключевые слова предназначены для фактических слов, тем более что у вас уже есть набор для ключевых слов:

for log_line in log_lines:
    if keywords.intersection(set(log_line.split()):
        print log_line
0 голосов
/ 18 января 2019

Предложенное решение печатает строки, которые содержат несколько ключевых слов так же часто, как и количество ключевых слов, которые у них есть, что может быть тем, чего вы хотите избежать. Кроме того, если ключевое слово появляется как часть другого слова, оно также появляется (хотя это соответствует поведению grep).

Некоторые решения:

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)])
...