2017-02-05 7 views
0

Мне нужно извлечь (много) информацию из разных текстовых файлов. Интересно, если есть более короткий и более эффективный способ, чем следующее:лучший способ извлечь данные с помощью re.compiler

Первая часть: (N строк длиной)

N1 = re.compile(r'') 
N2 = re.compile(r'') 
. 
Nn = re.compile(r'') 

Вторая часть: (длинные 2N линии)

with open(filename) as f: 
    for line in f: 
    if N1.match(line): 
     var1 = N1.match(line).group(x).strip() 
    elif N2.match(line): 
     var2 = N1.match(line).group(x).strip() 
    elif Nn.match(line): 
     varn = Nn 

Рекомендуете ли вы, чтобы re.compile vars (часть 1) отдельно от части 2. Что вы используете в этом случае? Возможно, функция pasing regex как аргумент? и называть его каждый раз.

В моем случае N равно 30, то есть у меня есть 90 строк для подачи словаря с очень небольшим количеством или вообще никакой логики.

+1

В общем, если вы хотите 'n' вещи, используйте * список *. – jonrsharpe

+0

извлеченные данные будут храниться в списках и словарях, но зачем использовать список перед извлечением? –

+0

... потому что вы хотите что-то более короткое и более эффективное, чем определение 'n' скомпилированных регулярных выражений с отдельными именами? – jonrsharpe

ответ

0

Я собираюсь попытаться ответить на этот вопрос, не зная, что вы на самом деле там делает. Таким образом, этот ответ может помочь вам, а может и нет.

Прежде всего, то, что re.compile делает, предварительно скомпилирует регулярное выражение, поэтому вы можете использовать его позже и не нужно его компилировать каждый раз, когда вы его используете. Это в первую очередь полезно, когда у вас есть регулярное выражение, которое используется несколько раз в вашей программе. Но если выражение используется только несколько раз, то на самом деле не так много пользы для его составления.

Итак, вы должны спросить себя, как часто выполняется код, который пытается сопоставить все эти выражения. Это один раз во время выполнения скрипта? Затем вы можете сделать свой код проще, вставив выражения. Поскольку вы используете совпадения для каждой строки в файле, предварительная компиляция, вероятно, имеет смысл здесь.

Но только потому, что вы предварительно скомпилировали выражение, это не означает, что вы должны быть неаккуратными и слишком часто совпадать с одним и тем же выражением. Посмотрите на этот код:

if N1.match(line): 
    var1 = N1.match(line).group(x).strip() 

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

Вместо этого, просто соответствовать его один раз, а затем повторно использовать результат:

n1_match = N1.match(line) 
if n1_match: 
    var1 = n1_match.group(x).strip() 

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

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

+0

Большинство предварительно скомпилированных RE будут использоваться один раз (или два) для каждого файла, но скрипт будет работать сотню файлов каждый день. Да. Они взаимоисключающие, если они соответствуют строке, я на 100% уверен, что у этой строки не будет никакой другой информации. Я знаю структуру файла, поэтому, если я знаю, что в последней строке всегда есть данные, которые мне нужны, я полагаю, что последний раз. В конце for, каждый var будет кормить 3 dicts. По этой причине у меня есть эти вары. Основной дикт будет питаться более или менее 110 файлами. Я действительно не знаю, является ли это лучшим способом получения данных из более или менее структурированного текста/журнала fi. –

+0

Если сценарий выполняется несколько раз, но процесс Python, выполняющий его, заканчивается между ними, то предварительная компиляция выражений не поможет. – poke

0

Как упоминалось в re module documentation, регулярные выражения, которые вы проходите через методы re, кэшируются: в зависимости от количества выражений, которые у вас есть, их кэширование может оказаться нецелесообразным.

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

regexes = map(re.compile, ['', '', '', '', ...]) 
vars = ['']*len(regexes) 
with open(filename) as f: 
    for line in f: 
    for i,regex in enumerate(regexes): 
     if regex.match(line): 
     var[i] = regex.match(line).group(x).strip() 
     break # break here if you only want the first match for any given line. 
+0

Обратите внимание, что код OP останавливается в первом совпадении, в то время как ваш цикл всегда будет соответствовать всем выражениям. – poke

+0

@poke Вы правы, я обновил свой пример. – Faibbus