извлекать строку с регулярным выражением нестабильно - PullRequest
0 голосов
/ 10 октября 2011

Доброе раннее утро,

У меня есть следующий файл регулярных выражений Python, который мы создали в предыдущем посте. Это предназначено для извлечения любой информации, которая выглядит как 'chr' + number + ':' + bignumber ".." + bignumber (так что это выглядит как chr1: 100000..120000) если chr1 переключен на chrX, скрипт regex больше не работает ...

Вот оригинальный скрипт:

    # Opens each file to read/modify
    infile='myfile.txt'
    outfile='outfile.txt'

    #import Regex
    import re

    with open (infile, mode='r', buffering=-1) as in_f, open (outfile, mode='w', buffering=-1) as out_f:
        f = (i for i in in_f if '\t' in i.rstrip())
        for line in f:
            _, k = line.split('\t',1)
            x = re.findall(r'^1..100\t([+-])chr(\d+):(\d+)\.\.(\d+).+$',k)
            if not x:
                continue
            out_f.write(' '.join(x[0]) + '\n')

Если я изменил эту строку:

    x = re.findall(r'^1..100\t([+-])chrX(\d+):(\d+)\.\.(\d+).+$',k)

Я не могу извлечь что-то конкретно, что выглядит как chrX и т. Д ... Также вы должны знать, что некоторые строки могут быть пустыми!

Помогите пожалуйста :) Спасибо

1 Ответ

3 голосов
/ 10 октября 2011

Я не до конца понимаю ваш вопрос, но постараюсь дать совет, основанный на вашем коде.

Вот самая важная строка:

x = re.findall(r'^1..100\t([+-])chr(\d+):(\d+)\.\.(\d+).+$',k)

Замечания:

0) Я даже не знаю, что buffering=-1 сделает при звонке на open(). Я рекомендую вам избавиться от этого и разрешить стандартное поведение - буферизацию строки. Это то, что вы хотите для этого случая, когда вы хотите обрабатывать файл по одной строке за раз. (Значение по умолчанию совпадает с указанием buffering=1.)

1) re.findall() возвращает список совпадений. Однако, используя $ в своем паттерне, вы гарантируете, что получите не более одного совпадения, потому что каждая строка может иметь только один конец строки. Поэтому вам, вероятно, следует использовать re.search(). Вы даже можете использовать re.match(), поскольку у вас есть ^ для привязки к началу строки.

2) Я не рекомендую использовать метод метода .split(), чтобы избавиться от ведущей вкладки. Просто сложите вкладку в ваше регулярное выражение. Это проще и быстрее.

3) Ваш шаблон требует, чтобы каждая строка начиналась с такой строки:

1aa100
100100
1xx100
1xy100

Это то, что вы хотели? Каждая строка начинается с числа, которое всегда заканчивается на «100»? Если это всегда число, вы можете использовать \d вместо . в шаблоне.

4) Вам нужна вкладка после числа, подобного номеру, которое соответствует приведенному выше. Затем у вас есть группа совпадений, которая соответствует либо «+», либо «-» и позволяет вам собрать соответствующее значение. Мне любопытно, что вы будете с этим делать.

5) Шаблон chr\d+ будет соответствовать chr0, chr1, chr11, chr111 и т. Д. Любая комбинация цифр с минимальной длиной 1 цифра. Я не уверен, ожидаете ли вы, что он на самом деле будет совпадать с заглавной 'X' (вы говорили о совпадении chrX), но это определенно не будет.

6) Вы сопоставляете число, два фактических периода и другое число. Это выглядит совершенно правильно и хорошо для меня. Затем, после второго числа, вы используете . и + вместе. Для этого требуется один или несколько дополнительных символов до конца строки. Мне интересно, если это вызывает вашу проблему. Возможно, вам следует использовать .*, который соответствует нулю или большему количеству дополнительных символов?

7) Если вы используете re.match() вместо re.findall(), вам не нужно будет использовать x[0], чтобы попасть в группу совпадений.

8) Если у вас есть группа совпадений m, ' '.join(m) не работает. Вы получаете ошибку типа. Вам нужно использовать ' '.join(m.groups()) вместо.

9) Я думаю, что шаблон с chr и двумя числами, разделенными .., сам по себе довольно хорош, так что, возможно, вы можете расслабить оставшуюся часть шаблона и просто сопоставить их.

10) Мне всегда нравится предварительно компилировать шаблоны регулярных выражений. Это быстрее, и тогда вы можете использовать функции метода в скомпилированном шаблоне. Например, если pat является предварительно скомпилированным регулярным выражением, вы можете использовать pat.search(line) для поиска строки текста.

Соберите мои предложения, и вот пример кода Python, который вы можете попробовать:

import re

infile='myfile.txt'
outfile='outfile.txt'

pat = re.compile(r'([+-])chr([^:]+):(\d+)\.\.(\d+)')

with open(infile, mode='r') as in_f, open(outfile, mode='w') as out_f:
    for line in in_f:
        if '\t' not in line.rstrip():
            continue
        m = pat.search(line)
        if not m:
            continue
        out_f.write(' '.join(m.groups()) + '\n')

РЕДАКТИРОВАТЬ: Поскольку вы, кажется, хотите признать строку chrX как действительную, я изменил приведенный выше пример кода. Вместо \d для сопоставления с цифрой теперь используется [^:] для сопоставления с чем угодно, кроме двоеточия. Приведенный выше код должен соответствовать chr1:, chrX: или почти всем остальным.

...