Как я могу напечатать только строки с пятью или более совпадениями регулярного выражения?

Я пытаюсь использовать регулярные выражения в Python для синтаксического анализа большого текстового файла с разделителями табуляции построчно и печати строк, в которых строка содержит 5 или более экземпляров 0/1 или 1/1.

Мой скрипт почти готов, но я борюсь с 5 или более экземплярами.

Это напечатает строки с одним совпадением.

import re  
f = open ("infile.txt", "r")  
out = open("outfile.txt", "w")  

for line in f:  
    if re.match(r"(.*)(0|1)/(1)(.*)", line):  
        print >> out, line,

Чтобы напечатать только строки, имеющие 5 или более совпадений, я попробовал findall и finditer следующим образом, но они не сработали:

for line in f:  
    x = len(re.findall(r"(.*)(0|1)/(1)(.*)", line)):  
    if x > 5:  
        print >> out, line,

Кто-нибудь может мне с этим помочь?

Вот пример одной строки из текстового файла (в файле все пробелы — табуляции):

X 6529 . C A,G PASS AC=4,2;AF=0.6777 1/1:0,20 0/1:0,16 0/1:0,16 0/0:4,16 0/0:3,1 

person prepagam    schedule 06.04.2013    source источник
comment
Как это не работает? Можете ли вы исправить отступ?   -  person tacaswell    schedule 06.04.2013


Ответы (2)


Вы можете использовать {5,} для соответствия шаблону 5 или более раз.

import re
f = open ("data.txt", "r")
out = open("dataout.txt", "w")

for line in f:
    if re.match(r"(.*([01]/1.*){5,}", line):
        print >> out, line,
person gonz    schedule 06.04.2013

Я думаю, что есть два решения, которые могут сработать. Первый придерживается вашей текущей идеи о выполнении findall с шаблоном, который соответствует одному вхождению 0/1 или 1/1. Второй — создать единый шаблон, который будет соответствовать этому тексту пять раз одновременно.

Для первого подхода, я думаю, все, что вам нужно сделать, это избавиться от .astericssymbol бит вашего текущего шаблона (я действительно не понимаю, почему это прописано, а не .*, но это неправильно в любом случае). Вот код, который должен работать:

for line in f:
    matches = re.findall(r'[01]/1', line)
    if len(matches) >= 5:
        print >> out, line,

Я удалил группы захвата, которые были ненужны и могли немного замедлить работу.

Для второго подхода вы можете сделать всего один вызов re.search, который вернет значение, отличное от None, только если найдет 5 совпадений соответствующего вида. Шаблон использует синтаксис повторения, {N}, чтобы найти ровно N копий предыдущего шаблона. В этом случае нам нужно будет сопоставить дополнительные символы между битами 0/1 или 1/1, поэтому к шаблону добавлено .*. Поскольку мы хотим повторить все это, нам нужно обернуть его в группу без захвата:

for line in f:
    if re.search(r'(:?[01]/1.*){5}', line):
        print >> out, line,
person Blckknght    schedule 06.04.2013