2010-11-15 3 views
2

При переходе через одну из проблем в Python Challenge, я пытаюсь решить следующим образом:Поиск и захватывая символ с использованием регулярных выражений Python

Читать ввод в текстовом файле с символами следующим образом:

DQheAbsaMLjTmAOKmNsLziVMenFxQdATQIjItwtyCHyeMwQTNxbbLXWZnGmDqHhXnLHfEyvzxMhSXzd 
BEBaxeaPgQPttvqRvxHPEOUtIsttPDeeuGFgmDkKQcEYjuSuiGROGfYpzkQgvcCDBKrcYwHFlvPzDMEk 
MyuPxvGtgSvWgrybKOnbEGhqHUXHhnyjFwSfTfaiWtAOMBZEScsOSumwPssjCPlLbLsPIGffDLpZzMKz 
jarrjufhgxdrzywWosrblPRasvRUpZLaUbtDHGZQtvZOvHeVSTBHpitDllUljVvWrwvhpnVzeWVYhMPs 
kMVcdeHzFZxTWocGvaKhhcnozRSbWsIEhpeNfJaRjLwWCvKfTLhuVsJczIYFPCyrOJxOPkXhVuCqCUgE 
luwLBCmqPwDvUPuBRrJZhfEXHXSBvljqJVVfEGRUWRSHPeKUJCpMpIsrV....... 

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

Питона сценарий, который я написал, чтобы сделать выше выглядит следующим образом:

import re 

pattern = re.compile("[a-z][A-Z]{3}([a-z])[A-Z]{3}[a-z]") 
f = open('/Users/Dev/Sometext.txt','r') 
for line in f: 
    result = pattern.search(line) 
    if result: 
     print result.groups() 

f.close() 

выше данный сценарий, вместо возвращения захвата (список строчных букв), возвращает все текстовые блоки, которые встречают критерии регулярного выражения, такие как

aXCSdFGHj 
vCDFeTYHa 
nHJUiKJHo 
......... 
......... 

Может кто-нибудь сказать мне, что именно я делаю неправильно здесь? И вместо того, чтобы перебирать весь файл, существует ли альтернативный способ запуска поиска регулярных выражений по всему файлу?

Благодаря

ответ

2

Изменение result.groups() к result.group(1), и вы получите только одного матча письмо.

Вторая проблема с вашим кодом заключается в том, что он не найдет несколько результатов в одной строке. Поэтому вместо использования re.search вам понадобится re.findall или re.finditer. findall вернет строки или кортежи строк, тогда как finditer возвращает объекты совпадения.

Вот где я подошел с той же проблемой:

import urllib 
import re  

pat = re.compile('[a-z][A-Z]{3}([a-z])[A-Z]{3}[a-z]') 
print ''.join(pat.findall(urllib.urlopen(
    "http://www.pythonchallenge.com/pc/def/equality.html").read())) 

Заметьте, что re.findall и re.finditer возврата непересекающиеся результаты. Поэтому при использовании вышеуказанного рисунка с re.findall в поиске по строке 'aBBBcDDDeFFFg', ваш единственный матч будет 'c', но не 'e'. К счастью, эта проблема Python Challenge не содержит таких подобных примеров.

+0

Спасибо за разъяснение. Я предполагаю, что urllib.urlopen ("http://www.pythonchallenge.com/pc/def/equality.html") .read() читает весь HTML в строку. Есть ли способ разбить его, чтобы вместо чтения всего HTML за один раз мы могли оптимизировать его, разбив его на более мелкие куски? –

+0

@sc_ray urllib.urlopen возвращает файл-подобный объект, поэтому вы можете читать строки за строкой, если хотите. –

+0

@sc_ray Хотя чтение строк за строкой может быть более эффективным, вы, вероятно, не заметите разницу в скорости и увеличении потребления памяти (но, конечно, вы должны знать об этом). – helpermethod

1
import re 

with open('/Users/Dev/Sometext.txt','r') as f: 
    tokens = re.findall(r'[a-z][A-Z]{3}([a-z])[A-Z]{3}[a-z]', f.read()) 

    for token ins tokens: 
     print token 

Что findall делает:

Возврат непересекающиеся матчи шаблона в строке, в виде списка строк. Строка сканируется слева направо и совпадает с , указанным в заказе. Если в шаблоне имеется одна или групп, верните список групп; этот будет списком кортежей, если шаблон имеет несколько групп. Пустые матчей включены в результат , если они не касаются начала другого матча.

Возможно, самая полезная функция в модуле re.

Функция read() считывает весь файл в большую строку. Это особенно полезно, если вам нужно сопоставить регулярное выражение со всем файлом.

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

+0

Метод - Спасибо за ответ. Можете ли вы каким-либо образом рассказать мне, что не так с фрагментом, который я предоставил. Я пытаюсь учиться на своих ошибках здесь. –

+0

@Steven Rumbalski - Можете ли вы рассказать о совпадающих совпадениях и о том, как регулярные выражения не обнаруживают таких совпадений? –

+0

@sc_ray Я удалил свой комментарий, потому что это не помогло решить этот вопрос Python Challenge. Однако я имел в виду тот факт, что 're.findall' и' re.finditer' возвращают неперекрывающиеся результаты. В этом случае 're.findall ('[az] [AZ] {3} ([az]) [AZ] {3} [az]', 'aBBBcDDDeFFFg')' найдет '' c'', но не ' 'e''. –

2

я предлагаю использовать lookaround:

(?<=[A-Z]{3})(?<![A-Z].{3})([a-z])(?=[A-Z]{3})(?!.{3}[A-Z]) 

Это не будет иметь никаких проблем с перекрытием спичек.

Объяснение:

(?<=[A-Z]{3}) # assert that there are 3 uppercase letters before the current position 
(?<![A-Z].{3}) # assert that there is no uppercase letter 4 characters before the current position 
([a-z])  # match a lowercase character (all characters in the example are ASCII) 
(?=[A-Z]{3}) # assert that there are 3 uppercase letter after the current position 
(?!.{3}[A-Z]) # assert that there is no uppercase letter 4 characters after the current position 
Смежные вопросы